在spring中,我个人认为依赖注入的方式有3种,分别是通过属性filed注入、构造方法注入、set方法注入。接下来通过代码具体分析一下。
@Autowired加在属性上,采用的是filed反射注入。
@Component
public class StayService {
@Autowired
private StayDao stayDao;
public void setStayDao(StayDao stayDao) {
System.out.println("-----set-------");
}
public void query(){
System.out.println(stayDao);
}
}
在上面的代码中。当我们向IndexDao中注入IndexService时,会去Spring容器中共寻找IndexService这个类型的bean,寻找的方式一般是根据byType,再byName去找。所以ByType和ByName再这里只是我们寻找bean的一主方式。它的注入是通过filed.set来注入的,而不是通过set方法。
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(AppConfig.class);
StayService service = acc.getBean(StayService.class);
service.query();
}
}
这里根本没有调用set方法,但是stayDao这已经有值了(没有打印set方法里的字符串)。所以这里是通过filed.set反射注入进来的。
@Autowired加在构造方法上(也可以不加@Autowired注解)通过构造方法注入。
@Component
public class StayService {
// @Autowired
private StayDao stayDao;
@Autowired
public StayService(StayDao stayDao){
this.stayDao = stayDao;
System.out.println("构造方法 "+this.stayDao);
}
public void setStayDao(StayDao stayDao) {
System.out.println("-----set-------");
}
// public void query(){
// System.out.println(stayDao);
// }
}
@Autowired加在set方法上采用的是set方法反射注入。
@Component
public class StayService {
private StayDao stayDao;
@Autowired
public void setStayDao(StayDao stayDao) {
System.out.println("-----set-------"+stayDao);
}
}
打印结果
这里跟set方法的名字没有任何关系,方法名字可以随便取。参数类型符合就行。
假设我们需要开发一个中间件,类似于MyBatis的。来看一下下面的这段代码。
//1、需要把StayService动态加载到Spring容器```
public class StayService {
//2、需要把StayDao注入到StayService
private StayDao stayDao;
public void setStayDao(StayDao stayDao) {
System.out.println("-----set-------"+stayDao);
}
}
因为这里是模拟开发中间件,所以我们不能依赖Spring,也就是不能使用@Component和@Autowired注解将他们注入进来。我们先来考虑在不使用@Autowired注解的情况下如何将StayDao注入到StayService中来。
1、假设StayService已经存在容器中
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition stayService = (GenericBeanDefinition)beanFactory.getBeanDefinition("stayService");
stayService.setAutowireMode(2);
}
}
这里我将StayService的BeanDefinition取出来,将它的AutowireMode模式设置为了2,2代表通过set方法注入,它会去寻找writeMethod,也就是以set开头,符合spring定义的规则的方法,这里会找到setStayDao方法将StayDao注入进来。当然实现的方式有很多种,这只是其中一种。打印结果如下。
2、不依赖spring将StayService放入Spring容器中,并注入StayDao。
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(StayService.class).getBeanDefinition();
beanDefinition.setAutowireMode(2);
registry.registerBeanDefinition("stayService",beanDefinition);
}
}
通过实现ImportBeanDefinitionRegistrar拿到注册器,将类转换为beanDefinition并修改setAutowireMode,再将它注入到spring容器中。如果仅仅只是还是不行的。我们还需要借助@Import注解将MyRegistrar这个类交给spring去解析。
@Configuration
@ComponentScan("com")
@Import(MyRegistrar.class)
public class AppConfig {
}