BeanFactory 的实现以及常见 ApplicationContext 实现
BeanFactory实现
DefaultListableBeanFactory
DefaultListableBeanFactory,是 BeanFactory 最重要的实现,像控制反转和依赖注入功能,都是它来实现
下面我们试着自己实现一下Bean的注入
public class TeastBeanFactory1 {
public static void main(String[] args) {
// 首先我们定义一个DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class, scope, 初始化, 销毁)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
// 注册
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 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean1() {
log.debug("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("构造 Bean2()");
}
}
}
此时运行打印结果只有一个bean的名字 config
但是因为我们的代码中也有写@Configuration注解,然后配置类中也进行了bean注入,为什么没有其他的bean呢?
这就说明我们的注解没有被解析!!也就是说DefaultListableBeanFactory没有解析注解的能力!
那么怎么能让它的功能变得完整呢?答案就是给 BeanFactory 添加一些常用的后处理器
后处理器入门
public class TeastBeanFactory1 {
public static void main(String[] args) {
// 首先我们定义一个DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class, scope, 初始化, 销毁)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
// 注册
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
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 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean1() {
log.debug("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("构造 Bean2()");
}
}
}
注意此时只是加入了后处理器,还并没有对注解进行处理
此时的输出只是多了几个后处理器的bean
下面添加运行后处理器的代码
public class TeastBeanFactory1 {
public static void main(String[] args) {
// 首先我们定义一个DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class, scope, 初始化, 销毁)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
// 注册
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// BeanFactory 后处理器主要功能,补充了一些 bean 定义
// BeanFactoryPostProcessor是internalConfigurationAnnotationProcessor后处理器的类型
// 这里就是运行这些后处理器
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
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 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean1() {
log.debug("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("构造 Bean2()");
}
}
}
输出
现在我们将bean1和bean2都注入到了我们的beanfactory了,那我们再来试一试能否获得到我注入到bean1中的bean2呢?
我添加了如上代码
运行结果
我们看到了bean1的初始化,可是bean2是null,这说明我们的Autowired注解没有生效
我又又 运行了bean后处理器
运行结果
bean2成功获取到
单例对象的创建时机
我们在代码中添加一条分割线,观察输出
我们看到beanfactory中注入的对象都是懒加载的
我们想让他在调用之前就创建,效果如下
bean后处理器的顺序
我们从代码的这一行的方法进去
看到了添加bean后处理器的方法
我想知道@Resource和@Autowired的执行顺序
public class TeastBeanFactory1 {
public static void main(String[] args) {
// 首先我们定义一个DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class, scope, 初始化, 销毁)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
// 注册
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// BeanFactory 后处理器主要功能,补充了一些 bean 定义
// BeanFactoryPostProcessor是internalConfigurationAnnotationProcessor后处理器的类型
// 这里就是运行这些后处理器
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
beanFactory.preInstantiateSingletons();// 准备好所有的单例
System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
//System.out.println(beanFactory.getBean(Bean1.class).getBean2());
System.out.println(beanFactory.getBean(Bean1.class).getInter());
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
@Bean
public Bean3 bean3() {
return new Bean3();
}
@Bean
public Bean4 bean4() {
return new Bean4();
}
}
interface Inter {
}
static class Bean3 implements Inter {
}
static class Bean4 implements Inter {
}
static class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean1() {
log.debug("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
@Autowired
@Resource(name = "bean4")
private Inter bean3;
public Inter getInter() {
return bean3;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("构造 Bean2()");
}
}
}
我新增了两个bean,bean3和bean4
然后向bean1中用两种方式注入bean3和bean4,通过bean1.getInter()方法来测试优先级
结果如下:
@Autowired优先
我又又改了一下bean后处理器的运行方法,输出了一下后处理器
再次证明!
另外这个顺序也是可以改的,通过
这样改完顺序就会改变
原因是两个后处理器都实现了Order接口,都有一个决定优先级的order,调用这个方法后就根据order重新排序了。
常见 ApplicationContext 实现
ClassPathXmlApplicationContext
类的定义
结果
FileSystemXmlApplicationContext
如何使用BeanFactory实现上述两种ApplicationContext
AnnotationConfigApplicationContext
我们可以看到,相比较前两种ApplicatContext,AnnotationConfigApplicationContext的bean容器中多了后处理器和config对象
正是这些后处理器帮忙识别被注解的类和方法,实现的bean注入
那么,ClassPathXmlApplicationContext如何加载这些后处理器呢?
只需要在xml文件中加入一行<context:annotation-config/>
AnnotationConfigServletWebServerApplicationContext
运行结果
访问
学到了什么
a. 常见的 ApplicationContext 容器实现
b. 内嵌容器、DispatcherServlet 的创建方法、作用
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)