-
前言
在看博主这篇文章之前,请大家思考一个问题:spring@Autowired和@Resource这两个注解是干嘛用的?很多人会回答,@Autowired是通过byType注入属性的,@Resource默认使用byName注入,也可以使用byType方式注入,在你们眼里可能觉得这两个注解就是Spring开启不同注入方式的方法,不使用这两个注解或者不在xml中配置的话就不能注入,但其实spring的byType与@Autowired是完全两码事,原因如何我们往下看。
-
正文
我们来看下面这段代码:
@Component
public class UserClass {
private OrderClass orderClass;
public OrderClass getOrderClass() {
return orderClass;
}
public void setOrderClass(OrderClass orderClass) {
this.orderClass = orderClass;
}
}
public class TestAUtowired {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext
= new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(annotationConfigApplicationContext.getBean(UserClass.class).getOrderClass()+"-----");
}
}
我们在一个UserClass中引入另一个OrderClass,并提供setter、getter方法,然后打印出getOrderClass的值,很显然是空的:
接下来,我们实现自己的一个Registar:
public class MyRegistar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
GenericBeanDefinition genericBeanDefinition =
(GenericBeanDefinition)registry.getBeanDefinition("userClass");
genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
registry.registerBeanDefinition("userClass",genericBeanDefinition);
}
}
并且通过javaConfig的方式import进去:
可以看到,这个对象有值了:
在这过程中,我既没使用@Autowired也没使用@Resource,也没有使用xml进行配置,但是为什么我能注入OrderClass这个对象呢?这个其实就是你们对spring了解的局限性,我们来看org.springframework.beans.factory.support.AbstractBeanDefinition这个类中有四个属性:
它包含了spring的四中注入方式,在默认的情况下,spring使用的是第一种AUTOWIRE_NO,也就是不自动装配,当你使用了@Autowired或者@Resource时候就会使用自动装配,而如何装配则是通过定义的属性,来完成注入,但是使用@Autowired注入时必须依赖你引入的对象,而spring使用的byType注入时只需要提供setter方法的。上面的MyRegistar就是这个作用,将默认的装配方式改为了byType,只要提供setter方法就可以将属性注入,也就是说,当你想使用byType的时候,可以不加任何注解,也不需要引入任何变量,只需要把默认的装配方式改为AUTOWIRE_BY_TYPE就可以了,然后提供setter方法即可。
关于这里的应用,可能大家开发过程中没有使用,但是其实MyBatis中队其做了完美的运用,我们来看org.mybatis.spring.annotation.MapperScannerRegistrar这个类,这里面在调用了org.mybatis.spring.mapper.ClassPathMapperScanner的processBeanDefinitions()方法,在这个方法的最后一段,将自动装配方式改成了AUTOWIRE_BY_TYPE
并且在
org.mybatis.spring.support.SqlSessionDaoSupport中提供了setter方法给SqlSession赋予了新的实现sqlSessionTemplate,
对这些不了解的童鞋可以看博主这篇文章 https://mp.csdn.net/postedit/85619155。
-
总结
- spring默认使用的装配规则是不自动装配----AUTOWIRE_NO
- 当你加了@Autowired或者@Resource时候就会使用自动装配
- 如果想使用byType方式装配的话,可以不加任何注解或者配置,也不需要引入对象,只需实现org.springframework.context.annotation.ImportBeanDefinitionRegistrar,将默认装配方式改了,然后提供setter和getter方法就行了,byName同理