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

    技术2022-07-11  147

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

    修改完成

    Processed: 0.009, SQL: 9