当前位置: 首页 > 工具软件 > Autowire > 使用案例 >

AbstractBeanDefinition的autowireMode自动装配模式属性

鲁才艺
2023-12-01

在AbstractBeanDefinition中有一个属性是autowireMode,该属性表示自动装配模式

在Spring中,注入方式有两种

  1. 通过set方法
  2. 通过构造函数(如果有多个构造函数会选择参数多的构造方法)

手动装配注入:

  • @Resource: 默认是通过name来查找注入值,如果不存在就报错

  • @Autowired 通过类型查找(类型),然后再通过name

AutowireMode(自动装配模型):在spring中有四种模式分别是:

  1. AUTOWIRE_NO = 0:默认装配模式,目前非xml配置都是使用这种方式,需要使用手动装配注入

  2. AUTOWIRE_BY_NAME = 1: 通过set方法,并且set方法的名称需要和bean的name一致

  3. AUTOWIRE_BY_TYPE = 2: 通过set方法,并且再根据bean的类型,注入属性,是通过类型配置

  4. AUTOWIRE_CONSTRUCTOR = 3: 通过构造器注入

模式说明
no(默认)不采用自动装配autowire机制。Bean 引用必须由 ref 元素定义。对于较大的部署,不建议更改默认设置(也就是说,官方推荐使用autowire_no),因为明确指定协作者可以提供更好的控制和清晰度。 在某种程度上,它记录了系统的结构。
byName通过属性的名称自动装配(注入)
Spring会在容器中查找名称与bean属性名称一致的bean,并自动注入到bean属性中;当然bean的属性需要有setter方法。
例如:bean A有个属性master,master的setter方法就是setMaster,A设置了autowire=“byName”,那么Spring就会在容器中查找名为master的bean通过setMaster方法注入到A中。
byType通过类型自动装配(注入)
Spring会在容器中查找类(Class)与bean属性类一致的bean,并自动注入到bean属性中,如果容器中包含多个这个类型的bean,Spring将抛出异常。如果没有找到这个类型的bean,那么注入动作将不会执行。
constructor类似于byType,但是是通过构造函数的参数类型来匹配
假设bean A有构造函数A(B b, C c),那么Spring会在容器中查找类型为B和C的bean通过构造函数A(B b, C c)注入到A中。与byType一样,如果存在多个bean类型为B或者C,则会抛出异常。但时与byType不同的是,如果在容器中找不到匹配的类的bean,将抛出异常,因为Spring无法调用构造函数实例化这个bean。
/**
 * Constant that indicates no autowiring at all.
 * @see #setAutowireMode
 * 默认的装配模式: 这种方式不能进行自动注入,需使用@Resource或@Autoried注解注入
 */
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
/**
 * Constant that indicates autowiring bean properties by name.
 * @see #setAutowireMode
 * 这种是通过属性的名字来自动注入,不过需要提供set方法,如果没有提供set方法也是空
 * 
 */
public static final int AUTOWIRE_BY_NAME=AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
 * Constant that indicates autowiring bean properties by type.
 * @see #setAutowireMode
 * 通过属性类型来自动注入: 同时也是通过set方法来赋值的
 */
public static final int AUTOWIRE_BY_TYPE=AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
 * Constant that indicates autowiring a constructor.
 * @see #setAutowireMode
 * 通过构造器自动注入
 */
public static final int AUTOWIRE_CONSTRUCTOR=AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

AbstractAutowireCapableBeanFactory#populateBean方法中,对AutowireMode的判断

            int resolvedAutowireMode = mbd.getResolvedAutowireMode();
            if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
                MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                if (resolvedAutowireMode == 1) {
                    this.autowireByName(beanName, mbd, bw, newPvs);
                }

                if (resolvedAutowireMode == 2) {
                    this.autowireByType(beanName, mbd, bw, newPvs);
                }

                pvs = newPvs;
            }

代码如下:

@Component
public class ConsumerA {
    private ProviderA providerA;
    public void setProviderA(ProviderA a) {
        this.providerA = a;
    }
    public void providerShow() {
        System.out.println(providerA);
    }
}
@Component
public class ProviderA {}
// 配置类,组件扫描根路径
@Configuration
@ComponentScan("com.modules.test")
public class TestConfig {
}
@Component
public class TestBeanFactoryProcessor implements BeanFactoryPostProcessor {
    private static final String BEAN_NAME = "consumerA";
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        //获取ConsumerA类的Bean定义
        AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(BEAN_NAME);
        //修改ConsumerA类的装配模式autowireMode,默认值为AUTOWIRE_NO,不进行自动装配
        beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
    }
}
public class ProcessorMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(TestConfig.class);
        ConsumerA consumer = context.getBean(ConsumerA.class);
        consumer.providerShow();
        System.err.println(context.getBean(ProviderA.class));
        context.close();
    }
}

在上面的代码中,我们没有在ConsumerA类中的ProvierA属性加@Autowired或者@Resource注解,但是我们在TestBeanFactoryProcessor中修改了ConsumerA的装配模式,因此ConsumerA中的ProviderA还是会注入进去的。

如果使用默认的AUTOWIRE_NO装配模式,则不会自动注入进去,需要使用@Autowired或者@Resource

参考AutowireMode的一些理解

 类似资料: