您现在的位置是:首页 >其他 >进阶Spring(2)-BeanFactory和ApplicationContext实现网站首页其他
进阶Spring(2)-BeanFactory和ApplicationContext实现
🏠个人主页:阿杰的博客
💪个人简介:大家好,我是阿杰,一个正在努力让自己变得更好的男人👨
目前状况🎉:24届毕业生,奋斗在找实习的路上🌟
🚗🚗为了让更多的人看到更优质的博客,阿杰正在努力的更新学习中心中的内容。
第二讲:BeanFactory和ApplicationContext实现
首先看代码
ConfigurableApplicationContext context = SpringApplication.run(BeanfactoryimpApplication.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//class org.springframework.beans.factory.support.DefaultListableBeanFactory
System.out.println(beanFactory.getClass());
spring底层创建实体类就是依赖于DefaultListableBeanFactory。他是BeanFactory接口的一个主要实现类。
先创建类
package com.ajie.beanfactoryimp.newbean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 15:56
*/
@Slf4j
public class Bean1 {
public Bean1(){
log.debug("构造 Bean1");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2(){
return bean2;
}
}
package com.ajie.beanfactoryimp.newbean;
import lombok.extern.slf4j.Slf4j;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 15:56
*/
@Slf4j
public class Bean2 {
public Bean2(){
log.debug("构造 Bean2");
}
}
package com.ajie.beanfactoryimp.newbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 15:55
*/
@Configuration
public class Config {
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
开始创建测试类
package com.ajie.beanfactoryimp.newbean;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 15:52
*/
public class TestBeanFactory {
public static void main(String[] args) {
//spring底层创建实体类依赖这个类 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//定义名字为config的bean
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config",beanDefinition);
//给BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
//BeanFactory的运行后处理器 可以解析@Configuration @Bean
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}
可以看到@Bean被扫描 bean1 和bean2 被创建 @Configuration
是用于spring
类扫描的时候用的,加了这个注解的类被扫描到了就会被放进Bean
工厂
在加上这句代码
System.out.println(beanFactory.getBean(Bean1.class).getBean2());
会看到
为什么呢? 因为beanFactory并没有解析@Autowired, @Resource…
加上
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
bean2就被创建出来了
**注意: **
BeanFactory中的对象都是懒加载的,如果不去调用get()方法获取的话,就不会初始化,如果想要让对象在get()之前就创建好,需要调用beanFactory.preInstantiateSingletons()
方法。
总结:
beanFactory 不会做的事
- 不会主动调用BeanFactory的后处理器
- 不会主动添加Bean的后处理器
- 不会主动初始化单例
- 不会解析BeanFactory,还不会解析 ${}, #{}
下面咱们在添加一点类
先定义一个接口Inter,再定义两个Bean,名称分别为Bean3和Bean4,都继承Inter,接着在Config中通过@Bean注解将Bean3和Bean4都加进Bean工厂中,然后在Bean1中定义一个Inter对象,通过@Autowired注解将实现类注入进来。
package com.ajie.beanfactoryimp.newbean;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 23:07
*/
public interface Inter {
}
package com.ajie.beanfactoryimp.newbean;
import lombok.extern.slf4j.Slf4j;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 23:08
*/
@Slf4j
public class Bean4 implements Inter{
public Bean4() {
log.debug("构造 bean4 ");
}
}
package com.ajie.beanfactoryimp.newbean;
import lombok.extern.slf4j.Slf4j;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 23:08
*/
@Slf4j
public class Bean3 implements Inter{
public Bean3() {
log.debug("构造 bean3 ");
}
}
package com.ajie.beanfactoryimp.newbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author ajie
* @version 1.0
* @date 2023/5/2 15:55
*/
@Configuration
public 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();
}
}
bean1 中添加
@Autowired
private Inter inter;
public Inter getInter(){
return inter;
}
这是因为@Autowired 注解会先根据名字来匹配 没有的话 再根据类型来匹配 但是bean3和bean4都实现了inter所以会出现错误
只需要吧inter改成 bean3就可以避免错误
如果我们在加上 @Resource(name=“bean4”)
这个时候他注册的是那个?
运行后发现注册的是 bean3 ;
在beanFactory 加载后处理器的时候处理@Autowired注解的处理器internalAutowiredAnnotationProcessor比internalCommonAnnotationProcessor先进入,所以@Autowired会先被解析