您好,登錄后才能下訂單哦!
自動注解實現Spring IOC和事務管理的示例分析,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
IOC即控制反轉,我們要把對象的創建通過注解來實現
@Service
類中聲明了@Service注解的對象,我們就對它的實例化進行管理。(這里注解的名字無所謂,我們實現相應的功能即可)
@Autowired
類中的屬性聲明了@Autowired注解的,我們就對該屬性進行依賴注入 在程序運行前,我們通過掃描所有的類文件,然后找出聲明了@Service
注解的類,進行實例化,然后加入到我們的一個Map集合中,同時查找該類中是否有聲明@Autowired
注解的屬性,并進行標記。 再次遍歷聲明了@Service
注解的類,然后注入聲明@Autowired
注解屬性的類。這樣我們就把對象的創建以及依賴的注入完成了。
事務管理需要我們遵循事務的ACID原則
@Transactional
類中或者方法中聲明了@Transactional注解的我們就要對改對象或者方法添加事務控制功能 首先我們先掃描所有類文件,找出聲明了@Transactional
注解的類或者方法,準備好一個List集合,如果注解聲明在類上,我們就把類中所有的方法放入集合中,如果注解是在方法上,我們直接把方法加入到List集合中。 然后我們通過代理(動態代理或者cglib代理)給這些方法添加事務控制功能
public interface ApplicationContext { Object getBean(String name); <T> T getBean(String name, Class<T> requiredType); }
這是一個核心配置類,主要實現了以下三個功能
獲取所有配置了@Service注解的類,并實例化,放入Map中
對于類中添加@Autowired注解的屬性進行依賴注入
對于添加了@Transactional注解的屬性或者方法進行事務增強
public class AnnotationConfigApplicationContext implements ApplicationContext { /** * 存放bean */ private final Map<String, BeanDefinition> beanMap = 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<String> 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<String, BeanDefinition> next : beanMap.entrySet()) { BeanDefinition beanDefinition = next.getValue(); //如果有AutoWired注解,設置值 if (beanDefinition.isAutoWired()) { Object object = beanDefinition.getBeanObject(); Class<?> definitionClass = object.getClass(); List<String> 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<String, BeanDefinition> next : beanMap.entrySet()) { BeanDefinition definition = next.getValue(); //獲取需要開啟事務管理的類下的所有方法 List<Method> 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<String> 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> T getBean(String name, Class<T> requiredType) { Object o = beanMap.get(name).getBeanObject(); if (o.getClass() == requiredType) { return (T) o; } return null; } }
對于事務的增強,我們需要依賴代理來實現。代理我們使用了動態代理和cglib代理兩種,對于需要代理對象實現接口的,我們使用動態代理;對于沒有實現接口的對象,我們使用cglib代理。下面看下具體實現。
public interface AopProxy { /** * 創建帶事務的代理 * * @param o 代理對象 * @param methods 代理對象中需要添加事務的方法 * @return 增強之后的代理對象 */ abstract Object createProxyWithTransaction(Object o, List<Method> methods); }
public class DynamicProxy implements AopProxy { @Override public Object createProxyWithTransaction(Object o, List<Method> methods) { 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; }); } }
public class CglibProxy implements AopProxy { @Override public Object createProxyWithTransaction(Object o, List<Method> methods) { 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和事務管理的示例分析的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。