1.BeanFactory与ApplicationContext
BeanFactory的功能:
-
BeanFactory是spring中核心的一个顶层接口,是spring的核心容器
-
主要职责是生产bean
-
使用了简单工厂的设计模式,通过调用getBean(标识)获取一个Bean
-
有非常多的实现类,每个工厂都有不同的职责功能,最强大的工厂是DefaultListableBeanFactory。spring底层是使用DefaultListableBeanFactory进行生产bean
-
是ApplicationContext的父接口,主要的ApplicationContext实现都组合了BeanFactory的功能
-
控制反转、基本的依赖注入、bean的生命周期的各种功能都有BeanFactory的实现类提供
以SpringBoot启动类代码举例
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
System.out.println("启动完成");
ConfigurableApplicationContext run = SpringApplication.run(Application.class);
}
}
ApplicationContext的功能
run方法返回的结果是ConfigurableApplicationContext,这个类继承于ApplicationContext。
- 从UML图上看出,Spring的核心容器BeanFactory是ApplicationContext的父接口。
- ApplicationContext实现组合了BeanFactory的功能,并且扩展了BeanFactory的功能。
@SpringBootApplication
public class SpringStudyApplication {
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext context = SpringApplication.run(SpringStudyApplication.class, args);
System.out.println("*********扩展MessageResource*********");
System.out.println("*********功能:国际化*********");
System.out.println(context.getMessage("hi", null, Locale.CHINESE));
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
System.out.println("*********扩展ResourcePatternResolver*********");
System.out.println("*********功能:获取资源*********");
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource:resources){
System.out.println(resource);
}
System.out.println("*********扩展EnvironmentCapable*********");
System.out.println("*********功能:获取配置信息*********");
context.getEnvironment().getProperty("java_home");
context.getEnvironment().getProperty("server.port");
}
}
输出结果
BeanFactory的实现
①先创建beanfactory的核心容器实例对象,DefaultListableBeanFactory是bean加载的核心部分,是Spring注册及加载的默认实现。
②创建bean定义对象beanDefinition,bean的描述信息包括(class,scope,初始化方法,销毁方法),创建Config,bean1,bean2实例bean
③将bean定义对象beanDefinition注册到beanfactory,此时beanfactory中就有了一个名为config的bean
public class TestBeanFactory {
public static void main(String[] args) {
//DefaultListableBeanFactory是bean加载的核心部分,是Spring注册及加载的默认实现
//刚创建好,DefaultListableBeanFactory内部没有任何bean定义
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//bean的定义(class,scope,初始化方法,销毁方法)
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class)
.setScope("singleton").getBeanDefinition();
//注册,,完成以后beanFactory里面就多了一个名字为config的bean
beanFactory.registerBeanDefinition("config",beanDefinition);
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
@Configuration
static class Config{
@Bean
public Bean1 bean1(){return new Bean1();}
@Bean
public Bean2 bean2(){return new Bean2();}
}
static class Bean1{
public Bean1(){
System.out.println("构造Bean1");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2(){
return bean2;
}
}
static class Bean2{
public Bean2(){
System.out.println("构造Bean2");
}
}
}
输出结果:
但此时,只是将名为Config的类注册到了beanfactory中,并不能解析其中@Bean和@Config注解的功能
④给beanfactory添加一些bean的后处理器
//给 beanfactory添加一些常用的后处理器,
//internalConfigurationAnnotationProcessor处理@Configuration注解
//internalAutowiredAnnotationProcessor处理@Autowired注解
//internalCommonAnnotationProcessor处理@Resource注解
//internalEventListenerProcessor
//internalEventListenerFactory
// 有了后处理器就可以解析注解的能力(解析@Configuration,@Bean等)
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
//根据一个类型获取多个bean
//BeanFactory后处理器的主要功能,补充了一些bean的定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class)
.values()
.stream()
.forEach(beanFactoryPostProcessor->{
//执行beanFactory后处理器
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
输出结果:
但此时,不能解析@Autowried注解
System.out.println(beanFactory.getBean("bean2"));
System.out.println(beanFactory.getBean(Bean1.class).getBean2());
输出结果:成功输出bean1中的bean2
添加Bean后处理器,对@Autowired @Resource进行解析处理
//添加Bean后处理器,对@Autowired @Resource进行解析处理
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
输出结果:成功输出bean1中的bean2
//提前构造号所有的单例对象,不加此代码,则使用bean时才会创建bean
beanFactory.preInstantiateSingletons();