自动注解实现SpringIOC和事务管理的示例分析
自动注解实现Spring IOC和事务管理的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
10年积累的网站设计制作、做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有东宝免费网站建设让你可以放心的选择与我们合作。
自定义注解实现spring的IOC以及事务管理功能
思路分析
IOC
IOC即控制反转,我们要把对象的创建通过注解来实现
@Service
类中声明了@Service注解的对象,我们就对它的实例化进行管理。(这里注解的名字无所谓,我们实现相应的功能即可)@Autowired
类中的属性声明了@Autowired注解的,我们就对该属性进行依赖注入 在程序运行前,我们通过扫描所有的类文件,然后找出声明了@Service
注解的类,进行实例化,然后加入到我们的一个Map集合中,同时查找该类中是否有声明@Autowired
注解的属性,并进行标记。 再次遍历声明了@Service
注解的类,然后注入声明@Autowired
注解属性的类。这样我们就把对象的创建以及依赖的注入完成了。
事务管理功能
事务管理需要我们遵循事务的ACID原则
@Transactional
类中或者方法中声明了@Transactional注解的我们就要对改对象或者方法添加事务控制功能 首先我们先扫描所有类文件,找出声明了@Transactional
注解的类或者方法,准备好一个List集合,如果注解声明在类上,我们就把类中所有的方法放入集合中,如果注解是在方法上,我们直接把方法加入到List集合中。 然后我们通过代理(动态代理或者cglib代理)给这些方法添加事务控制功能
代码实现(只列出核心代码片段)
创建ApplicationContext接口
public interface ApplicationContext { Object getBean(String name);T getBean(String name, Class requiredType); }
创建AnnotationConfigApplicationContext对象,实现接口方法
这是一个核心配置类,主要实现了以下三个功能
获取所有配置了@Service注解的类,并实例化,放入Map中
对于类中添加@Autowired注解的属性进行依赖注入
对于添加了@Transactional注解的属性或者方法进行事务增强
public class AnnotationConfigApplicationContext implements ApplicationContext { /** * 存放bean */ private final MapbeanMap = new HashMap<>(); /** * 先把包名转换为路径,首先得到项目的classpath */ private final String CLASSPATH = this.getClass().getResource("/").getPath(); public AnnotationConfigApplicationContext(String... basePackages) { try { scanPackages(basePackages); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } /** * 扫描所有包 并实现bean对象的创建,依赖注入,增强事务 * @param basePackages * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ private void scanPackages(String[] basePackages) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // 设置获取所有配置Service注解的对象 setBeanDefinition(basePackages); // 设置依赖关系 setBeanDepend(); // 设置事务增强 setTransaction(); } /** * 获取所有需要管理的对象 * * @param basePackages 需要扫描的包 * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ private void setBeanDefinition(String[] basePackages) throws ClassNotFoundException, IllegalAccessException, InstantiationException { // 获取所有类路径下的class文件 List classPaths = new ArrayList<>(); for (String basePackage : basePackages) { //然后把我们的包名basPath转换为路径名 basePackage = basePackage.replace(".", File.separator); //然后把classpath和basePack合并 String searchPath = CLASSPATH + basePackage; getFile(classPaths, new File(searchPath)); } // 找出所有有@Service注解的类,加入到beanMap中 for (String s : classPaths) { s = s.replace(CLASSPATH, "").replace("/", ".").replace(".class", ""); Class clazz = Class.forName(s); Service service = (Service) clazz.getAnnotation(Service.class); if (service != null) { BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setBeanObject(clazz.newInstance()); // 设置bean name String value = service.value(); // 如果没有自定义bean name,设置bean name为class name if ("".equals(value)) { value = clazz.getName(); value = value.substring(value.lastIndexOf(".") + 1); value = value.substring(0, 1).toLowerCase() + value.substring(1); } beanDefinition.setBeanName(value); // 是否有依赖关系 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { declaredField.setAccessible(true); Autowired autowired = declaredField.getAnnotation(Autowired.class); // 如果类属性有@Autowired注解,把依赖对象放入BeanDefinition的dependBeanName集合中 if (autowired != null) { beanDefinition.setAutoWired(true); beanDefinition.getDependBeanName().add(declaredField.getName()); } } // 是否有父接口,为后面增强使用动态代理还是cglib代理做准备 Class[] interfaces = clazz.getInterfaces(); if (interfaces.length > 0) { beanDefinition.setHaveParent(true); } // 是否有事务注解,如果有加入到BeanDefinition对象的transactionMethods属性中 Annotation annotation = clazz.getAnnotation(Transactional.class); Method[] methods = clazz.getDeclaredMethods(); //如果@Transactional注解出现在类上面,把类下所有的方法都加入到待添加事务的列表中 if (annotation != null) { for (Method method : methods) { beanDefinition.getTransactionMethods().add(method); } } else { // 如果@Transactional在某个方法上面,把该方法加入到BeanDefinition对象的transactionMethods属性中 for (Method method : methods) { Transactional methodAnnotation = method.getAnnotation(Transactional.class); if (methodAnnotation != null) { beanDefinition.getTransactionMethods().add(method); } } } // 将添加事务之后的对象重新加入到beanMap中 beanMap.put(beanDefinition.getBeanName(), beanDefinition); } } } /** * 遍历所有bean,找出有依赖关系的bean,注入 */ private void setBeanDepend() { for (Map.Entry next : beanMap.entrySet()) { BeanDefinition beanDefinition = next.getValue(); //如果有AutoWired注解,设置值 if (beanDefinition.isAutoWired()) { Object object = beanDefinition.getBeanObject(); Class> definitionClass = object.getClass(); List beanNames = beanDefinition.getDependBeanName(); beanNames.forEach(w -> { try { // 获取需要进行注入的对象 Field declaredField = definitionClass.getDeclaredField(w); // 暴力访问 declaredField.setAccessible(true); // 给依赖对象赋值 declaredField.set(object, getBean(w)); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } }); // 组装好的对象重新放入map中 beanMap.put(beanDefinition.getBeanName(), beanDefinition); } } } /** * 配置事务增强 */ private void setTransaction() { for (Map.Entry next : beanMap.entrySet()) { BeanDefinition definition = next.getValue(); //获取需要开启事务管理的类下的所有方法 List transactionMethods = definition.getTransactionMethods(); ProxyFactory proxyFactory = new ProxyFactory(); // 根据代理对象是实现接口,来决定采用动态代理还是cglib代理 if (!definition.isHaveParent()) { proxyFactory = new ProxyFactory(new CglibProxy()); } //给方法配置事务增强 Object withTransaction = proxyFactory.getProxyWithTransaction(definition.getBeanObject(), transactionMethods); definition.setBeanObject(withTransaction); //把增强之后的对象重新放入到beanMap中 beanMap.put(next.getKey(), definition); } } private void getFile(List classPaths, File file) { //文件夹递归 if (file.isDirectory()) { File[] files = file.listFiles(); if (files != null) { for (File f1 : files) { getFile(classPaths, f1); } } } else { //标准文件获取class文件 if (file.getName().endsWith(Constant.FILE_TYPE_CLASS)) { //如果是class文件我们就放入我们的集合中。 classPaths.add(file.getPath()); } } } @Override public Object getBean(String name) { return beanMap.get(name).getBeanObject(); } @Override public T getBean(String name, Class requiredType) { Object o = beanMap.get(name).getBeanObject(); if (o.getClass() == requiredType) { return (T) o; } return null; } }
事务增强的实现
对于事务的增强,我们需要依赖代理来实现。代理我们使用了动态代理和cglib代理两种,对于需要代理对象实现接口的,我们使用动态代理;对于没有实现接口的对象,我们使用cglib代理。下面看下具体实现。
创建AopProxy接口
public interface AopProxy { /** * 创建带事务的代理 * * @param o 代理对象 * @param methods 代理对象中需要添加事务的方法 * @return 增强之后的代理对象 */ abstract Object createProxyWithTransaction(Object o, Listmethods); }
动态代理DynamicProxy的实现
public class DynamicProxy implements AopProxy { @Override public Object createProxyWithTransaction(Object o, Listmethods) { return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), (proxy, method, args) -> { Object invoke = null; boolean anyMatch = methods.stream().anyMatch(w -> w.getName().equals(method.getName())); if (anyMatch) { TransactionManager.getInstance().beginTransaction(); try { invoke = method.invoke(o, args); TransactionManager.getInstance().commit(); } catch (Exception e) { TransactionManager.getInstance().rollback(); throw e; } return invoke; } invoke = method.invoke(o, args); return invoke; }); } }
cglib代理的实现
public class CglibProxy implements AopProxy { @Override public Object createProxyWithTransaction(Object o, Listmethods) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(o.getClass()); enhancer.setCallback((MethodInterceptor) (o1, method, objects, methodProxy) -> { Object invoke; boolean anyMatch = methods.stream().anyMatch(w -> w.getName().equals(method.getName())); if (anyMatch) { TransactionManager.getInstance().beginTransaction(); try { invoke = method.invoke(o, objects); TransactionManager.getInstance().commit(); } catch (Exception e) { TransactionManager.getInstance().rollback(); throw e; } return invoke; } invoke = method.invoke(o, objects); return invoke; }); return enhancer.create(); } }
看完上述内容,你们掌握自动注解实现Spring IOC和事务管理的示例分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
分享名称:自动注解实现SpringIOC和事务管理的示例分析
当前URL:http://abwzjs.com/article/gdojco.html