一.举例
1.创建三个类
@Configuration
static class Config{
@Bean
public A beanA(){
return new A();
}
@Bean
public B beanB(){
return new B();
}
}
static class A{
public A(){
log.info("调用了A的构造方法");
}
}
static class B{
@Autowired
private A a;
public B(){
log.info("调用了B的构造方法");
}
}
2.创建beanFactory
public static void main(String[] args) {
//1.获取beanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//2.bean的定义,单例模式,类型
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class)
.setScope("singleton").getBeanDefinition();
//3.给beanFactory添加定义器
beanFactory.registerBeanDefinition("config",beanDefinition);
//3.给beanFactory添加一些常用注解处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
//4.给beanFactory添加后处理器
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream()
.forEach(postProcessor -> {
postProcessor.postProcessBeanFactory(beanFactory);
});
//6.打印注入到容器中的bean
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
运行结果
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanA
beanB
可以看到beanFactory把Config,A,B的对象都创建出来了
我们可以看到在B类中通过@AutoWired自动注入了A,那么我们来尝试获取这个A对象,看是否可以获取到它
A beanA = beanFactory.getBean(B.class).a;
System.out.println(beanA);
运行结果:
null
发现并没有创建这个A的对象,这是因为beanFactory没有实现对@Autowried的实现,我们需要添加bean的后处理器
3.bean后处理器
//7.添加bean的后处理器
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
//获取A
A a = beanFactory.getBean(B.class).a;
System.out.println(a);
运行结果:
21:47:19.239 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了B的构造方法
21:47:19.244 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA'
21:47:19.245 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了A的构造方法
com.example.springioc.component.TestBeanFactory$A@d9345cd
可以看到这次成功创建了A的对象
4.bean的延迟创建
beanFactory会的bean的创建延迟,查看一下执行顺序,在获取A对象之前添加分隔符
运行查看结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanA
beanB
21:49:00.784 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
21:49:00.785 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
--------------------------
21:49:00.788 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB'
21:49:00.789 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
21:49:00.799 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了B的构造方法
21:49:00.804 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA'
21:49:00.805 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了A的构造方法
com.example.springioc.component.TestBeanFactory$A@d9345cd
可以看到刚开始只是声明了bean的定义,并没有创建bean对象,调用getBean()时才创建了bean对象
下面我们调用
//8.让bean对象提前创建
beanFactory.preInstantiateSingletons();
再次运行查看结果:
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanA
beanB
21:53:08.726 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
21:53:08.727 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
21:53:08.730 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
21:53:08.733 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA'
21:53:08.740 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了A的构造方法
21:53:08.741 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB'
21:53:08.741 [main] INFO com.example.springioc.component.TestBeanFactory - 调用了B的构造方法
--------------------------
com.example.springioc.component.TestBeanFactory$A@5a45133e
进程已结束,退出代码0
可以看到在定义完bean之后就创建了bean对象
二.Autowired和Resource的顺序
1.Autowired注入
我们知道这俩注解都是实现依赖注入的,那么他们的顺序是怎样的?
我们定义C和D类,让它们都实习Com接口
interface Com{}
static class C implements Com{
public C(){log.info("调用了C的构造方法");}
}
static class D implements Com{
public D(){log.info("调用了D的构造方法");}
}
}
然后我们创建E类,给它注入Com类型的成员变量
static class E{
@Autowired
private Com beanC;
public E(){log.info("调用了E的构造方法");}
}
把C,D,E都写入Config配置类中:
@Bean
public C beanC(){
return new C();
}
@Bean
public D beanD(){
return new D();
}
@Bean
public E beanE(){
return new E();
}
那么C和D都实现了Com接口,我们知道Spring是单例模式的,现在有两个一样类型的bean,最终会注入哪个bean呢?我们只需要把变量名字写为c,它最终就会注入C类型的bean
2.@Autowired的规则
1.首先按照bean的类型注入
2.如果bean的类型一样有多个,那么按照bean的名字注入
我们运行一下,看一下是哪个类型的bean被注入了:
com.example.springioc.component.TestBeanFactory$C@6fdbe764
可以看到注入了C类型的bean!
3.@Qualifer注解
我们还可以添加@Qualifer注解来限定是哪个bean
@Autowired
@Qualifier("beanC")
private Com beanC;
4.同时添加两个注解
如果我们添加了两个注解,那么谁会注入进来呢?
@Autowired
@Resource(name = "beanD")
private Com beanC;
我们@Resource指定要注入beanD,@Autowired指定要注入beanC
查看运行结果:
com.example.springioc.component.TestBeanFactory$C@1e0b4072
可以看到最终注入了C类型的bean,这是为什么呢?让我们查看bean后处理器的添加顺序:
//7.添加bean的后处理器
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach((beanPostProcessor -> {
beanFactory.addBeanPostProcessor(beanPostProcessor);
System.out.println("=====>"+beanFactory);
}));
查看运行结果:
=====>org.springframework.beans.factory.support.DefaultListableBeanFactory@13c10b87: defining beans [config,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,beanA,beanB,beanC,beanD,beanE]; root of factory hierarchy
我们可以看到internalAutowiredAnnotationProcessor在internalCommonAnnotationProcessor的前面添加,所有先把@Autowired注入,在@Resource之前
那么我们如何改变加载顺序呢?我们可以使用比较器来改变加载顺序:
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream().sorted(
beanFactory.getDependencyComparator()
)
.forEach((beanPostProcessor -> {
beanFactory.addBeanPostProcessor(beanPostProcessor);
System.out.println("=====>"+beanFactory);
}));
我们在查看运行结果:
com.example.springioc.component.TestBeanFactory$D@4686afc2
可以看到注入了D类型的对象
原理就是调用了setOrder()方法,对其设置了优先级,使@Resource的优先级在@Autowired之前了