Spring注入 @Autowired和setter方式區別原理


pring 的注入方式有:setter、constructor、靜態工廠方法、實例工廠方法、注解@Autowired自動裝配幾種方式。

今天我們要了解的是:setter和@Autowired兩種方式的區別,常用的setter方式很好理解,通過調用Bean的屬性setter方法直觀的賦值即可。而@Autowired方式,沒有setter方法賦值又是通過什么方式實現的呢?看一下spring源碼:

1、AbstractAutowireCapableBeanFactory類中的autowireBean()方法

populateBean()方法:

2、AutowiredAnnotationBeanPostProcessor類中通過postProcessPropertyValues()方法很容易找到內部類AutowiredFieldElement.inject()方法:

通過上面的代碼很容易了解到,@Autowired方式是通過反射來設置屬性值的,噢。。。。。。。。。萬能而無節操的反射,明白了吧


@Autowired注解使用及原理

required屬性

  required屬性值可以為true( 默認值)和false。如果為true的話,沒有匹配的類則拋出異常;如果為false,則表示不是強制必須能夠找到相應的類,無論是否注入成功,都不會拋錯。

工作原理
 注解解析器:AutowiredAnnotationBeanPostProcessor

Spring容器啟動時,AutowiredAnnotationBeanPostProcessor被注冊到容器;
掃描代碼,如果帶有@Autowired注解,則將依賴注入信息封裝到InjectionMetadata中(見掃描過程);
創建bean時(實例化對象和初始化),會調用各種BeanPostProcessor對bean初始化,AutowiredAnnotationBeanPostProcessor負責將相關的依賴注入進來;

Spring 創建對象分為三個過程:

1、創建對象實例 Object obj = new Object() 或者 Object obj = new Object(xxx);
  AbstractAutowireCapableBeanFactory#createBeanInstance
2、依賴注入: obj.setXxx(xxx) {多個屬性就是 foreach}
  AbstractAutowireCapableBeanFactory#populateBean
3、Spring bean 擴展方法:init-method,BeanPostProcess,XXXAware 擴展
  AbstractAutowireCapableBeanFactory#initializeBean

@Autowired掃描過程

  1. 掃描當前類中標注@Autowired的屬性和方法;
  2. 再查找父類中注@Autowired的屬性和方法,依次遍歷;
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
        Class<?> targetClass = clazz;

        do {
            final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });

            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    return;
                }
                AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static methods: " + method);
                        }
                        return;
                    }
                    if (method.getParameterCount() == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                        }
                    }
                    boolean required = determineRequiredStatus(ann);
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            });

            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        }while (targetClass != null && targetClass != Object.class);
View Code

 

 

 

 

參考文章:

https://blog.csdn.net/wenluoxicheng/article/details/73608657

https://blog.csdn.net/yangguosb/article/details/84594129

https://juejin.im/entry/5ad3fda5f265da238d512a98


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM