美文网首页spring
spring的自动注入

spring的自动注入

作者: love111 | 来源:发表于2019-10-22 14:24 被阅读0次

研究spring源码,官网是一定要参考的
自动注入
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire
自动注入模型

自动注入模型.png

自动注入与手动注入
spring工厂在生成对象之后(没有进行属性填充不是bean,bean需要属性填充和经历完整生命周期),需要进行属性填充通过spring后置处理器的postProcessPropertyValues()方法
首先搞明白什么是自动注入,自动注入也可以叫做自动装配(springboot也有一个自动装配,springboot的应该叫做自动配置和这里说的自动注入是两回事,笔者不是什么大牛或者权威;所以读者如果你坚持认为springboot也叫自动装配那也无可厚非,只是在这篇文章里面所谓的自动注入就是自动装配,关于springboot的自动配置我以后再说),自动注入需要相对于手动装配来说。
DI(依赖注入)一共有两种主要的变体,分别是基于构造方法的依赖注入和基于setter(setXxxx(…))的依赖注入,不管是手动装配还是自动装配都是基于这两种方式或者变体方式来的;但是这里一定要回答到主要和变体两个名词,因为有的注入方式就不是这两种,而是这两种其中一种的变体方式;比如在一个类的属性上面加@Autowired,这种方式注入属性的方式就是利用了java的反射知识,field.set(value,targetObject);所以@Autowired这种注入的方式是setter注入方式的一种变体

xml或注解实现自动注入

首先根据四种自动注入模型进行理解,默认情况是no,BeanDefinition的属性autowireMode是AUTOWIRE_NO(0)。不自动进行注入。如果通过xml或修改BeanDefinition属性值为AUTOWIRE_BY_NAME(1),AUTOWIRE_BY_TYPE(2)可以

通过实现BeanFactoryPostProcessor可以修改beanDefinition 的AutowireMode

xml配置实现自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-autowire="byType">
        <!--自动装配-->
        <bean id="userService" class="com.service.Uservice">
        </bean>
        <bean id="indexService"  class="com.service.IndexService">
        </bean>
</beans>

package com.service;
public class IndexService  {
}


package com.service;
public class UserService  {

    IndexService indexService;


    //如果是自动装配需要提供setter方法或提供构造方法
 //构造方法 
  public UserService(IndexService indexService){
         this.indexService=indexService;
    }
   //set方法
    public void setIndexService(IndexService indexService) {
        this.indexService = indexService;
    }
    public void xx(){
        System.out.println(indexService);
    }
    
}


@ImportResource("classpath:spring.xml")
public class AppConfig {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext( AppConfig.class );
        UserService userService = (UserService) ac.getBean("userService" );
        userService.xx( );
    }
}


注解实现自动装配

package com.service;
import org.springframework.stereotype.Component;
@Component
public class IndexService  {
}


package com.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserService  {
    IndexService indexService;
    
      //如果是自动装配需要提供setter方法或提供构造方法
      //构造方法
      public UserService(IndexService indexService){
        this.indexService=indexService;
    }
       //set
    public void setIndexService(IndexService indexService) {
        this.indexService = indexService;
    }
    public void xx(){
        System.out.println(indexService);
    }

}

package com.service;
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition( "userService");
        beanDefinition.setAutowireMode( 1 );
                //beanDefinition.setAutowireMode( 2 );
        System.out.println(beanDefinition.getAutowireMode());

    }
}


package com;
@Configuration
@ComponentScan("com.service")
public class AppConfig {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext( AppConfig.class );
        UserService userService = (UserService) ac.getBean("userService" );
        userService.xx( );
    }
}

通过源码测试

populateBean.png
autowireByName.png
反射调用set方法.png

最后调用到程序得setIndexService()方法

所以可以这样理解:
自动注入模型有四种:no byname bytype constructor
自动注入方法有set和构造器方式
官网https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-constructor-injection

DI.png

使用@Autowired或@Resource注入

是一种手动注入


autowire.png inject.png
fieldset.png

@autowire属性注入调用链
AbstractAutowireCapableBeanFactory#populateBean
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
InjectionMetadata#inject
AutowiredFieldElement#inject
field.set(bean, value)

@autowire注入的实现类有多个

package com.service;
public interface C {
}

package com.service;
@Component
public class IndexService implements C {
}

package com.service;
@Component
public class IndexService1 implements C {
}

package com.service;
@Component
public class UserService  {
    @Autowired
        C indexService1;
    public void xx(){
        System.out.println(indexService1);
    }
}

basedtype.png
basedname.png

先通过类型type查找有两个,再通过name进行查找
所以,@autowire先通过type查找,如果查找到多个则再通过name查找,如果没有匹配的name则报错

@Resource
先通过name再通过bype进行查找
调用链
CommonAnnotationBeanPostProcessor#postProcessPropertyValues
InjectionMetadata#inject
InjectedElement#inject

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
                throws Throwable {

            if (this.isField) {
                Field field = (Field) this.member;
                ReflectionUtils.makeAccessible(field);
                field.set(target, getResourceToInject(target, requestingBeanName));
            }
            else {
                if (checkPropertySkipping(pvs)) {
                    return;
                }
                try {
                    Method method = (Method) this.member;
                    ReflectionUtils.makeAccessible(method);
                    method.invoke(target, getResourceToInject(target, requestingBeanName));
                }
                catch (InvocationTargetException ex) {
                    throw ex.getTargetException();
                }
            }
        }

field.set(target, getResourceToInject(target, requestingBeanName));


resource.png

可以证明先name,再从type查找
通过name没查找到则调用链如下
DefaultListableBeanFactory#resolveDependency
DefaultListableBeanFactory#doResolveDependency
DefaultListableBeanFactory#findAutowireCandidates
如果根据name查找到而类型不匹配则报错

populateBean方法

AbstractAutowireCapableBeanFactory#populateBean方法是实现注入的地方

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                      
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
                      //自动注入赋值
            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                               //手动注入 注解@Autowired 与@Resource
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        if (pvs != null) {
            applyPropertyValues(beanName, mbd, bw, pvs);//自动注入实现
        }
    }

autowireByName()和autowireByType()查找

protected void autowireByName(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            if (containsBean(propertyName)) {
                Object bean = getBean(propertyName);
                pvs.add(propertyName, bean);
                registerDependentBean(propertyName, beanName);
                if (logger.isDebugEnabled()) {
                    logger.debug("Added autowiring by name from bean name '" + beanName +
                            "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
                }
            }
            else {
                if (logger.isTraceEnabled()) {
                    logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                            "' by name: no matching bean found");
                }
            }
        }
    }


    protected void autowireByType(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }

        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            try {
                PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                // Don't try autowiring by type for type Object: never makes sense,
                // even if it technically is a unsatisfied, non-simple property.
                if (Object.class != pd.getPropertyType()) {
                    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                    // Do not allow eager init for type matching in case of a prioritized post-processor.
                    boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if (autowiredArgument != null) {
                        pvs.add(propertyName, autowiredArgument);
                    }
                    for (String autowiredBeanName : autowiredBeanNames) {
                        registerDependentBean(autowiredBeanName, beanName);
                        if (logger.isDebugEnabled()) {
                            logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                                    propertyName + "' to bean named '" + autowiredBeanName + "'");
                        }
                    }
                    autowiredBeanNames.clear();
                }
            }
            catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
            }
        }
    }

相关文章

  • spring源码解析-循环依赖

    讲解内容: spring的循环依赖---属性注入--自动注入 spring bean的生命周期 spring be...

  • spring注解--自动注入

    自动装配 @Autowired自动注入(Spring自动装配) 优先按照类名注入 如果容器中有多个相同的类,则会将...

  • 颠覆面试官的Spring自动注入

    Spring系列 - 你可能学了假的Spring 转载自: ---->>> 原文连接 在提到spring的自动注入...

  • Spring常用注解

    使用注解则Spring配置文件中autowire自动注入无效(自动注入autowire仅仅针对配置文件有效)@Co...

  • Spring自动注入

    一.自动注入 1.在 Spring 配置文件中对象名和 ref=”id”id 名相同使用自动注入,可以 不配置 2...

  • spring的自动注入

    研究spring源码,官网是一定要参考的自动注入https://docs.spring.io/spring-fra...

  • Spring自动装配

    1. @AutoWired,自动注入: 1.1 Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖...

  • spring泛形bean注入的2种方式

    spring泛形bean注入的2种方式 通过类继承的方式自动依赖注入extends 通过调用构造方法注入@Serv...

  • Spring 注解之@Autowired、@Qualifer以及

    @Autowired 按类型自动装配 1.Spring怎么知道注入哪个实现? 如果Spring配置了compone...

  • Spring自动装配的发展历程

    Spring所谓的自动装配,实质就是实现了对依赖注入的一个简化操作,而依赖注入就是Spring帮助你完成对象的组织...

网友评论

    本文标题:spring的自动注入

    本文链接:https://www.haomeiwen.com/subject/exjtvctx.html