91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

自動注解實現Spring IOC和事務管理的示例分析

發布時間:2021-11-15 16:37:22 來源:億速云 閱讀:131 作者:柒染 欄目:大數據

自動注解實現Spring IOC和事務管理的示例分析,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

自定義注解實現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> T getBean(String name, Class<T> requiredType);
}

創建AnnotationConfigApplicationContext對象,實現接口方法  

  這是一個核心配置類,主要實現了以下三個功能

  • 獲取所有配置了@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代理。下面看下具體實現。

創建AopProxy接口
public interface AopProxy {

    /**
     * 創建帶事務的代理
     *
     * @param o       代理對象
     * @param methods 代理對象中需要添加事務的方法
     * @return 增強之后的代理對象
     */
    abstract Object createProxyWithTransaction(Object o, List<Method> methods);
}
動態代理DynamicProxy的實現
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;
        });
    }
}
cglib代理的實現
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和事務管理的示例分析的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

尉氏县| 大洼县| 报价| 泉州市| 诸暨市| 民和| 玛曲县| 长顺县| 长治市| 新竹县| 简阳市| 旌德县| 邢台县| 布拖县| 崇阳县| 高清| 获嘉县| 探索| 崇仁县| 怀化市| 油尖旺区| 突泉县| 察隅县| 红桥区| 寻乌县| 崇州市| 成都市| 松潘县| 海原县| 平安县| 华亭县| 深圳市| 东宁县| 库伦旗| 石嘴山市| 天峨县| 多伦县| 安岳县| 策勒县| 沁源县| 邵东县|