在AbstractBeanDefinition中有一个属性是autowireMode,该属性表示自动装配模式
在Spring中,注入方式有两种
手动装配注入:
@Resource: 默认是通过name来查找注入值,如果不存在就报错
@Autowired 通过类型查找(类型),然后再通过name
AutowireMode(自动装配模型):在spring中有四种模式分别是:
AUTOWIRE_NO = 0:默认装配模式,目前非xml配置都是使用这种方式,需要使用手动装配注入
AUTOWIRE_BY_NAME = 1: 通过set方法,并且set方法的名称需要和bean的name一致
AUTOWIRE_BY_TYPE = 2: 通过set方法,并且再根据bean的类型,注入属性,是通过类型配置
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