基於之前的添加pom文件
<!--反射工具包-->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.12</version>
</dependency>
<!--工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
配置文件
basePackage=com.liu
註解
/**
* @Description 用於注入一個對象
* @ClassName Autowired 類名
* @Author 劉楠
* @date 2020.06.30
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* 依賴必須存在,不然就報錯
* @return
*/
boolean required() default true; //true就必須注入
}
/**
* @Description 用於標記一個類
* @ClassName Service 類名
* @Author 劉楠
* @date 2020.06.30
*/
@Documented
@Target(ElementType.TYPE) //只能用在類上
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
/**
* 類的id名稱
* @return
*/
String value() default "";//可以有也可以沒有
}
@Target({ElementType.TYPE}) //類上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Transactional {
/**
* 這個給個默認值也可以給空,工廠裏獲取也可以 這個省個事
* @return
*/
String value() default "transactionManager"; //默認事務管理器
}
在dao service TransactionManager ProxyFactory修改使用以上註解
- dao
@Service("accountDao")
public class JdbcAccountDaoImpl implements AccountDao {
@Autowired
private ConnectionUtils connectionUtils;
- service
@Service("transferService")
@Transactional
public class TransferServiceImpl implements TransferService {
// 最佳狀態
@Autowired
private AccountDao accountDao;
- TransactionManager
@Service("transactionManager")
public class TransactionManager {
@Autowired
private ConnectionUtils connectionUtils;
- ProxyFactory
@Service("proxyFactory")
public class ProxyFactory {
@Autowired
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
新增一個工具類
public class PropertiesUtils {
private static Properties props = new Properties();
public static Properties getProperties(String path) {
InputStream in = PropertiesUtils.class.getClassLoader().getResourceAsStream(path);
try {
props.load(in);
} catch (IOException e) {
e.printStackTrace();
}
return props;
}
}
修改 BeanFactory原來改名BeanFactoryOld不用,新建BeanFactory
public class BeanFactory {
private static Map<String, Object> map = new ConcurrentHashMap<>(); // 存儲對象
//默認要掃描的包,可通過配置文件來 如果配置文件中爲空就使用這個
private static String basePackage = "com.liu";
private static String basePackageKey = "basePackage";
static {
try {
/**
* 1.掃描指定包下的所有類,獲取指定註解的類的集合
* 2.使用反射創建對象
* 3.獲取Service注射標記的類
* 4.判斷註解value是否有值,有就放入容器
* 5.無值 如果有是類就獲取類名稱,並放入容器
* 6.無值情況下獲取接口的名稱,如果無值同時接口數量大於1就拋出異常
* 7.無值只有一個接口,獲取接口名稱放入容器
* 8.初始化完成
*/
doInitializationBean();
/**
* 判斷是否有Autowired,
*/
doAutowired();
/**
* Transactional註解標記的類
*/
doTransactional();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 初始化Bean,並放入容器中
* @throws InstantiationException
* @throws IllegalAccessException
*/
private static void doInitializationBean() throws InstantiationException, IllegalAccessException {
//1.加載配置因爲文件
Properties properties = PropertiesUtils.getProperties("base.properties");
String property = properties.getProperty(basePackageKey);
//如果配置文件中沒有,就用默認的
if (StringUtils.isBlank(property)) {
property = basePackage;
}
//2.使用反射工具類獲取所有帶Service註解的類
Reflections reflections = new Reflections(property);
//獲取所有Service註解的類
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Service.class);
//3. 通過反射實實例化
for (Class<?> clazz : classSet) {
//實例化通過無參數構造
Object newInstance = clazz.newInstance();
//獲取註解
Service annotation = clazz.getAnnotation(Service.class);
//獲取註解中的值
if(StringUtils.isBlank(annotation.value())) { //註解沒有值
//獲取接口類
Class<?>[] interfaces = clazz.getInterfaces();
if (interfaces.length > 1) { //判斷接口數量是否>1
throw new RuntimeException("該有多個父接口,並沒有指定名稱,請使用Service註解指定名稱");
}
if (interfaces.length == 0) { //接口數量爲0,沒有接口
//沒有接口就是個類獲取類名稱
String simpleName = clazz.getSimpleName();
//首字母小寫
String key = StringUtils.uncapitalize(simpleName);
//放入容器中
map.put(key,newInstance);
} else {
//接口數量爲1
//接口名稱
String simpleName = interfaces[0].getSimpleName();
//首字母小寫
String key = StringUtils.uncapitalize(simpleName);
//放入容器中
map.put(key,newInstance);
}
}else {
//註解中有值
//4.將類放入容器中
String id = annotation.value();
//首字母小寫
String key = StringUtils.uncapitalize(id);
//放入容器中
map.put(key,newInstance);
}
}
}
/**
* 注入
*/
private static void doAutowired() {
try {
//從容器中獲取循環判斷
for(Map.Entry<String,Object> entry:map.entrySet()){
//1.獲取創建的對象
String objKey = entry.getKey();
Object value = entry.getValue();
//2.獲取對象的類
Class clazz =value.getClass();
//獲取所有屬性字段
Field[] fields = clazz.getDeclaredFields();
//循環處理
for (Field field : fields) {
//3.判斷是否有Autowired註解
if(field.isAnnotationPresent(Autowired.class)&& field.getAnnotation(Autowired.class).required()){
//4.如果是有Autowired並且值是true,就從容器中去獲取對象
String simpleName = field.getType().getSimpleName();
//5.將首字母小寫
String key = StringUtils.uncapitalize(simpleName);
//獲取要注入的對象
Object o = map.get(key);
//沒有就異常
if(o==null){
throw new RuntimeException(simpleName+"依賴的對象不存在 是null");
}
//獲取這個類的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//6.找到對應字段set方法
if(method.getName().equalsIgnoreCase("set"+simpleName)){
//7.執行setter方法賦值
method.invoke(value, o);
}
}
}
}
/**
* 爲什麼不在這裏做事務,因爲事務代理工廠,也需要注入,可能沒有完成初始完成,放在下一輪中都實例和注入完成後,再代理
* public class ProxyFactory {
*
* @Autowired
* private TransactionManager transactionManager;
*/
//8.重新放入容器中
map.put(objKey, value);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 事務代理
*/
private static void doTransactional() {
for(Map.Entry<String,Object> entry:map.entrySet()) {
//1.獲取創建的對象
String key = entry.getKey();
Object value = entry.getValue();
//2.獲取屬性
Class clazz = value.getClass();
//3.判斷當前對象的類是否有Transactional
if(clazz.isAnnotationPresent(Transactional.class)){
//4.有這個註解說明要開啓事務,獲取代理工廠
ProxyFactory proxyFactory = BeanFactory.getBean("proxyFactory", ProxyFactory.class);
//5.判斷 這個對像是否有實現接口
Object proxyObj=null;
Class[] interfaces = clazz.getInterfaces();
//判斷有沒有接口
if(interfaces!=null&&interfaces.length>0){
//6.有接口使用jdk
proxyObj = proxyFactory.getJdkProxy(value);
}else{
//7.就是個類使用cglib
proxyObj = proxyFactory.getCglibProxy(value);
}
//8.重新放入容器中 將代理對象放入
map.put(key, proxyObj);
//10.完成代理
}
}
}
public static Object getBean(String id) {
return map.get(id);
}
public static <T> T getBean(String id,Class<T> clazz) {
return (T)map.get(id);
}
}
修改servlet
public class TransferServlet extends HttpServlet {
/**
* 通過工廠獲取Service
*/
private TransferService transferService = BeanFactory.getBean("transferService",TransferService.class) ;
修改完成