手动实现IOC与事务控制-JDBC-4-基于自定义注解

基于之前的添加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) ;

修改完成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章