Spring

BeanFactory和ApplicationContext

BeanFactory

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
public class SpringDemoTestApplication {
public static void main(String[] args) {
/**
* Class<?> primarySource-SpringDemoTestApplication:引导类
* String... args-agrs[] 应用程序参数
*/
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args);
}
}

image-20230609213239599

打开类图 我们可以发现:

BeanFactoryApplicationContext的父接口,是Spring核心容器,主要的ApplicationContext继承实现组合了它的方法

1
2
// 根据bean的名称检索bean的一个实例
context.getContext("name");

image-20230609214201934

image-20230609214619874

通过调试可以发现ApplicationContext里面包含BeanFactory对象

image-20230609215608098

BeanFactory功能

BeanFactory看似只有声明了这些接口,但是它的实现类提供了控制反转,依赖注入、Bean的声明周期的各种功能

image-20230609220127577

查看BeanFactory的一个实现类DefaultSingletonBeanRegistry,可以发现只是它组合了其他的父类

image-20230609221210849

查看其中的一个父类 DefaultSingletonBeanRegistry,它管理类所有的单例对象

image-20230609225158661

通过 反射 获取 DefaultSingletonBeanRegistry 类中成员属性 singletonObjects

1
2
3
4
5
6
   // 通过 反射 获取 DefaultSingletonBeanRegistry 类中成员属性 singletonObjects
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
map.entrySet().stream().forEach(stringObjectEntry -> System.out.println(stringObjectEntry.getKey() + "=>" + stringObjectEntry.getValue()));

image-20230609231049336

ApplicationContext

ApplicationContext的扩展功能主要继承于MessageSource,ResourcePatternResolver,ApplicationEventPublisher,EnvironmentCapable这些父接口

image-20230609231352094

MessageSource

1
context.getMessage("hi",null, Locale.CHINA)

image-20230609232803980

image-20230609232913040

ResourcePatternResolver

1
2
Resource resource = context.getResource("classpath:application.properties");
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");

image-20230609234203639

EnvironmentCapable

image-20230609234733197

1
2
// PropertyResolver
String property = context.getEnvironment().getProperty("server.port");

ApplicationEventPublisher

声明事件
1
2
3
4
5
6
7
8
9
10
public class DemoEvent extends ApplicationEvent {
/**
* 声明事件
*
* @param source 事件源
*/
public DemoEvent(Object source) {
super(source);
}
}
事件监听
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class Subscribe {
Logger logger = LoggerFactory.getLogger(Subscribe.class);

/**
* 事件监听
* @param demoEvent 事件类型
*/
@EventListener
public void subscribe(DemoEvent demoEvent) {
logger.info("demoEvent:" + demoEvent);
}
}
发送事件
1
2
3
4
5
6
7
8
9
10
11
@Component
public class Publish {
Logger logger = LoggerFactory.getLogger(Publish.class);

@Resource
private ApplicationEventPublisher applicationEventPublisher;

public void publish() {
applicationEventPublisher.publishEvent(new DemoEvent(applicationEventPublisher));
}
}
执行发送
1
2
3
        // ApplicationEventPublisher
// context.publishEvent(new DemoEvent(context));
context.getBean(Publish.class).publish();

image-20230610002025539

总结

BeanFactoryApplicationContext不仅仅是简单接口的继承关系,ApplicationContext组合并通过继承其他父类扩展了BeanFactory的功能

BeanFactory

BeanFactory的实现

首先,我们手动注册配置类定义信息和常见的后处理器,手动生成BeanFactory,添加后处理器并执行它们

我们查看BeanFactory一个默认的常见实现DefaultListableBeanFactory:

1
2
// beanFactory 根据 bean 的 定义(class\scope\初始化\销毁等) 创建对象
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

创建Bean对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Bean1 {
private Logger logger = LoggerFactory.getLogger(Bean1.class);

public Bean1 () {
logger.info("构造 Bean1");
}

@Resource
private Bean2 bean2;

public Bean2 getBean2() {
return bean2;
}
}

public class Bean2 {
private Logger logger = LoggerFactory.getLogger(Bean2.class);

public Bean2 () {
logger.info("构造 Bean2");
}
}


@Configuration
public class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}

@Bean
public Bean2 bean2() {
return new Bean2();
}
}

通过 BeanDefinition 定义Bean并注册到BeanFactory

BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值以及由具体实现提供的进一步信息

1
2
3
4
// 通过 BeanDefinition 定义Bean对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class)
// 设置 单例 模式
.setScope(ConfigurableBeanFactory.SCOPE_SINGLETON).getBeanDefinition();
1
2
// 注册到容器
beanFactory.registerBeanDefinition("config", beanDefinition);

image-20230610105106417

1
2
3
4
5
6
/**
* 根据 BeanDefinition Bean的定义 将 Bean 注入到 beanFactory
* 参数一:Bean 名称
* 参数二:BeanDefinition 定义
*/
beanFactory.registerBeanDefinition("config", beanDefinition);

注册后置处理器到 BeanFactory

1
2
 // 添加 注释处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

执行BeanFactory指定后处理器

1
2
3
4
// 根据 类的类型 获取 Bean集合
Map<String, BeanFactoryPostProcessor> beansOfType = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
// 执行 后处理器 补充Bean的定义
beansOfType.values().stream().forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

image-20230610131622294

获取依赖注入的Bean:查看 Bean1 中注入的 Bean2 对象,发现依赖注入并没有成功

1
2
// 查看 Bean1 中注入的 Bean2 对象
logger.info("Bean1 中注入的 Bean2 对象:{}", beanFactory.getBean(Bean1.class).getBean2());

image-20230610155552714

开启Bean后处理器,发现成功获取依赖注入的对象,但是对象是 懒汉式 的方式创建的

1
2
3
4
5
// Bean 后处理器 - 针对 Bean 生命周期的各个阶段提供扩展功能(例如:依赖注入)
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);

// 查看 Bean1 中注入的 Bean2 对象
logger.info("Bean1 中注入的 Bean2 对象:{}", beanFactory.getBean(Bean1.class).getBean2());

打开 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)方法,可以发现 后处理器 注册了 @Autowired@Resource 的处理器

image-20230610232839781

image-20230610155938299

可以通过BeanFactory的方法提前初始化所有的单例Bean

1
2
// 提前初始化所有的单例Bean
beanFactory.preInstantiateSingletons();

BeanFactory不会主动调用BeanFactory后处理器,不会添加Bean后处理器,不会主动初始化单例Bean,而是由ApplicationContext调用

定义接口 创建两个类实现同一接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface Inter {
}

public class Bean3 implements Inter {
private Logger logger = LoggerFactory.getLogger(Bean3.class);

public Bean3 () {
logger.info("构造 Bean3");
}
}


public class Bean4 implements Inter {
private Logger logger = LoggerFactory.getLogger(Bean4.class);

public Bean4 () {
logger.info("构造 Bean4");
}
}

Bean中使用 @Autowired依赖注入Inter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Bean1 {
private Logger logger = LoggerFactory.getLogger(Bean1.class);

public Bean1 () {
logger.info("构造 Bean1");
}

@Autowired
private Bean2 bean2;

public Bean2 getBean2() {
return bean2;
}

@Autowired
private Inter inter;

public Inter getinter() {
return inter;
}
}

image-20230610224249148

image-20230610224311078

@Autowire注解默认通过 ByType 方式注入,ByType方式没有找到再去根据 ByName方式寻找

1
2
3
4
5
6
@Autowired
private Inter bean3;

public Inter getBean3() {
return bean3;
}

image-20230610231418064

image-20230610231550064

@Resource优先根据ByName方式注入,默认情况下要求被注入的Bean必须存在,注解里name属性的优先级高于成员变量Name

1
2
3
4
5
6
@Resource(name = "bean4") 
private Inter bean3;

public Inter getBean3() {
return bean3;
}

image-20230610232305961

如果 @Resource@Autowired 的同时存在,优先注入 @Autowired

如果使用 依赖比较器 进行 排序 会发现 @Autowired 先生效,这是因为 两个后置处理器 的 order 值不一样,值越小的优先级越高

1
2
3
4
5
// Bean 后处理器 - 针对 Bean 生命周期的各个阶段提供扩展功能(例如:依赖注入)
beanFactory.getBeansOfType(BeanPostProcessor.class).values()
.stream()
.sorted(beanFactory.getDependencyComparator())
.forEach(beanFactory::addBeanPostProcessor);

image-20230610235515076

image-20230610235610031

image-20230610235622367

ApplicationContext常见实现和用法

常见实现

ClassPathXmlApplication

基于 classpathxml 格式配置文件来创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Bean5 {
private Logger logger = LoggerFactory.getLogger(Bean5.class);

private Bean6 bean6;

public Bean5 () {
logger.info("构造 Bean5");
}

public void setBean6(Bean6 bean6) {
this.bean6 = bean6;
}

public Bean6 getBean6() {
return bean6;
}
}
1
2
3
4
5
6
7
public class Bean6 {
private Logger logger = LoggerFactory.getLogger(Bean6.class);

public Bean6 () {
logger.info("构造 Bean6");
}
}
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean5" class="com.example.demo.bean.Bean5">
<property name="bean6" ref="bean6"></property>
</bean>
<bean id="bean6" class="com.example.demo.bean.Bean6"/>
</beans>
1
2
3
4
5
6
7
8
9
@Test
public void testClass() {
ClassPathXmlApplicationContext classPathXmlApplicationContext =
new ClassPathXmlApplicationContext("test.xml");
logger.info("查看 classPathXmlApplicationContext 中所有的容器");
Arrays.stream(classPathXmlApplicationContext.getBeanDefinitionNames())
.forEach(s -> logger.info(s));
logger.info("查看是否依赖注入是否成功:{}", classPathXmlApplicationContext.getBean(Bean5.class).getBean6());
}

image-20230613171023399

它的底层原理就是通过 XmlBeanDefinitionReader 加载配置文件 读取 bean 的定义至 beanFactory

1
2
3
4
5
6
7
8
// 底层原理
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(new ClassPathResource("test.xml"));
logger.info("查看 classPathXmlApplicationContext 中所有的容器");
Arrays.stream(beanFactory.getBeanDefinitionNames())
.forEach(s -> logger.info(s));
logger.info("查看是否依赖注入是否成功:{}", beanFactory.getBean(Bean5.class).getBean6());
FileSystemXmlApplicationContext

基于 磁盘 路径下的 xml 格式的配置文件来创建

1
2
3
4
5
6
7
8
9
@Test
public void testFileSystemXmlApplicationContext() {
FileSystemXmlApplicationContext fileSystemXmlApplicationContext =
new FileSystemXmlApplicationContext("src/main/resources/test.xml");
logger.info("查看 classPathXmlApplicationContext 中所有的容器");
Arrays.stream(fileSystemXmlApplicationContext.getBeanDefinitionNames())
.forEach(s -> logger.info(s));
logger.info("查看是否依赖注入是否成功:{}", fileSystemXmlApplicationContext.getBean(Bean5.class).getBean6());
}
AnnotationConfigServletWebApplicationContext

基于 注解配置类 来创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class BeanConfig {

@Bean
public Bean5 bean5(Bean6 bean6) {
Bean5 bean5 = new Bean5();
bean5.setBean6(bean6);
return bean5;
}

@Bean
public Bean6 bean6() {
return new Bean6();
}
}
1
2
3
4
5
6
7
8
9
10
@Test
public void testAnnotationConfigApplicationContext() {
AnnotationConfigApplicationContext annotationConfigApplicationContext
= new AnnotationConfigApplicationContext(BeanConfig.class);
logger.info("查看 classPathXmlApplicationContext 中所有的容器");
Arrays.stream(annotationConfigApplicationContext.getBeanDefinitionNames())
.forEach(s -> logger.info(s));
logger.info("查看是否依赖注入是否成功:{}", annotationConfigApplicationContext.getBean(Bean5.class).getBean6());
}

image-20230613173653358

AnnotationConfigServletWebApplicationContext

基于 注解配置类 来创建,用于web环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Configuration
public class WebConfig {
/**
* 创建 Tomcat 服务器
*
* @return
*/
@Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}

/**
* 创建 servlet 对象
*
* @return
*/
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}

/**
* 注册 dispatcherServlet 到 tomcat 服务器
*
* @param dispatcherServlet 通过 参数 注入
* @return
*/
@Bean
@Primary
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
// path:"/" 所有请求经过 DispatcherServlet 进行请求分发
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}

/**
* 创建 控制器
*
* @return
*/
@Bean("/hello")
public Controller controller() {
return (request, response) -> {
response.getWriter().write("Hello world!");
return null;
};
}
}
1
2
3
4
5
6
7
8
s    @Test
public void testAnnotationConfigServletWebApplicationContext() {
AnnotationConfigServletWebApplicationContext annotationConfigServletWebApplicationContext =
new AnnotationConfigServletWebApplicationContext(WebConfig.class);
logger.info("查看 classPathXmlApplicationContext 中所有的容器");
Arrays.stream(annotationConfigServletWebApplicationContext.getBeanDefinitionNames())
.forEach(s -> logger.info(s));
}

image-20230613193651853

Bean的生命周期

SpringBean的生命周期的各个阶段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class LifeCycleBean {

private static final Logger logger = LoggerFactory.getLogger(LifeCycleBean.class);

public LifeCycleBean() {
logger.debug("构造:LifeCycleBean");
}

@Autowired
public void autowired(@Value("${server.port}") String port) {
logger.debug("LifeCycleBean依赖注入:{}", port);
}

@PostConstruct
public void init() {
logger.debug("初始化:LifeCycleBean");
}

@PreDestroy
public void destroy() {
logger.debug("销毁:LifeCycleBean");
}
}
1
2
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args);
context.close();

image-20230613195350693

Bean 的生命周期:构造->依赖注入->初始化->销毁

添加一些 自定义 Bean 的后处理器,对于Bean的生命周期进行增强,完成生命周期的扩展

需要实现 InstantiationAwareBeanPostProcessorDestructionAwareBeanPostProcessor接口,这两个接口都继承于BeanPostProcessor

image-20230613200055801

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

private static final Logger logger = LoggerFactory.getLogger(CustomBeanPostProcessor.class);

/**
* Bean 实例化之前执行
*
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
logger.debug(">>>>实例化之前执行<<<<");
}
// 这里如果返回结果不能null 则会替代我们之前的bean
return null;
}

/**
* Bean 实例化之后执行
*
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
logger.debug(">>>>实例化之后执行<<<<");
}
// 如果返回false 则不会进行属性的依赖注入
return true;
}

/**
* Bean 依赖注入阶段执行
*
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
// @Resource等注释的解析
logger.debug(">>>>依赖注入阶段执行<<<<");
}
return pvs;
}

/**
* Bean 初始化执行之前执行
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
// @PostConstruct,@ConfigurationProperties等注释的解析
logger.debug(">>>>初始化之前执行 <<<<");
}
return bean;
}

/**
* Bean 初始化之后执行
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
// 代理增强
logger.debug(">>>>初始化之后执行 <<<<");
}
return bean;
}

/**
* Bean 销毁之前执行方法
*
* @param bean the bean instance to be destroyed
* @param beanName the name of the bean
* @throws BeansException
*/
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
logger.debug(">>>>销毁之前执行方法<<<<");
}
}
}

image-20230613202154385

模版设计模式

image-20230613211346813

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class DemoBeanFactory {

private static final Logger logger = LoggerFactory.getLogger(DemoBeanFactory.class);

public Object createBean() {
Object bean = new Object();
logger.info("构造 Bean");
logger.info("依赖注入 Bean");
// 添加 后处理器
for (BeanPostProcessor postProcessor : postProcessors) {
postProcessor.inject(bean);
}
logger.info("初始化 Bean");
return bean;
}

private List<BeanPostProcessor> postProcessors = new ArrayList<>();

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
postProcessors.add(beanPostProcessor);
}

public interface BeanPostProcessor {
void inject(Object bean);
}
}
1
2
3
4
5
6
7
@Test
public void testTemplate() {
DemoBeanFactory demoBeanFactory = new DemoBeanFactory();
demoBeanFactory.addBeanPostProcessor(bean -> logger.info("后处理器1"));
demoBeanFactory.addBeanPostProcessor(bean -> logger.info("后处理器2"));
demoBeanFactory.createBean();
}

Bean后处理器

Bean后处理器作用

Bean后处理器是 为Bean生命周期各个阶段提供扩展功能

GenericApplicationContext 探究一下 一些注解 分别由哪些处理器来解析的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class BeanReplica1 {

private static final Logger logger = LoggerFactory.getLogger(BeanReplica1.class);

private BeanReplica2 beanReplica2;

private BeanReplica3 beanReplica3;

private String port;

@Autowired
public void setBeanReplica2(BeanReplica2 beanReplica2) {
logger.info("@Autowired生效:{}", beanReplica2);
this.beanReplica2 = beanReplica2;
}

@Resource
public void setBeanReplica3(BeanReplica3 beanReplica3) {
logger.info("@Resource生效:{}", beanReplica3);
this.beanReplica3 = beanReplica3;
}

@Autowired
public void setPort(@Value("${server.port}") String port) {
logger.info("@Resource生效:{}", beanReplica3);
this.port = port;
}


@PostConstruct
public void init() {
logger.info("@PostConstruct生效");
}

@PreDestroy
public void destroy() {
logger.info("@PreDestroy生效");
}
}
public class BeanReplica2 {
}
public class BeanReplica3 {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void testGenericApplicationContext() {
// GenericApplicationContext 一个【干净】的容器 - 没有添加Bean工厂后处理器、Bean后处理器
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();

// 注册Bean
genericApplicationContext.registerBean("beanReplica1", BeanReplica1.class);
genericApplicationContext.registerBean("beanReplica2", BeanReplica2.class);
genericApplicationContext.registerBean("beanReplica3", BeanReplica3.class);


// 初始化容器 - 执行beanFactory后处理器 添加bean后处理器 初始化所有单例
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

// 销毁容器
genericApplicationContext.close();
}

在未添加后处理器的容器里 ,只注册了三个Bean实例

image-20230614000632415

1
2
3
4
5
@Data
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class Prop {
private String port;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Test
public void testGenericApplicationContext() {
// GenericApplicationContext 一个【干净】的容器 - 没有添加Bean工厂后处理器、Bean后处理器
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();

// 注册Bean
genericApplicationContext.registerBean("beanReplica1", BeanReplica1.class);
genericApplicationContext.registerBean("beanReplica2", BeanReplica2.class);
genericApplicationContext.registerBean("beanReplica3", BeanReplica3.class);
// 属性注入
genericApplicationContext.registerBean("prop", Prop.class);

// 设置 @Value 解析器
genericApplicationContext.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// @Autowired @Value 注释 后处理器
genericApplicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
// @Resource @PostConstruct @PreDestroy 后处理器
genericApplicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);
// @ConfigurationProperties 后处理器
ConfigurationPropertiesBindingPostProcessor.register(genericApplicationContext.getDefaultListableBeanFactory());

// 初始化容器 - 执行beanFactory后处理器 添加bean后处理器 初始化所有单例
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

System.out.println(genericApplicationContext.getBean(Prop.class));

// 销毁容器
genericApplicationContext.close();
}

image-20230614005108458

常见的后处理器

AutowiredAnnotationBeanPostProcessor 运行分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* AutowiredAnnotationBeanPostProcessor 运行分析
*/
@Test
public void testAutowiredAnnotationBeanPostProcessor() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 注册 Bean (参数一:bean 名称 参数二:实例化对象【不会进行创建过程,依赖注入】)
beanFactory.registerSingleton("beanReplica2", new BeanReplica2());
beanFactory.registerSingleton("beanReplica3", new BeanReplica3());
// 添加解析器
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 添加 ${} 解析器
beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

// 创建后处理器对象
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =
new AutowiredAnnotationBeanPostProcessor();
// 向 Bean 实例提供所属工厂的回调
autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);

BeanReplica1 beanReplica1 = new BeanReplica1();
logger.info("beanReplica1:{}", beanReplica1.toString());


// 在工厂将给定的属性值应用于给定的 Bean 之前对其进行后处理,而无需任何属性描述符 - 执行 依赖注入,@Autowired
autowiredAnnotationBeanPostProcessor.postProcessProperties(null, beanReplica1, "beanReplica1");

logger.info("bean1:{}", beanReplica1.toString());
}

image-20230614102549941

autowiredAnnotationBeanPostProcessor.postProcessProperties的执行过程

点击 进入 autowiredAnnotationBeanPostProcessor.postProcessProperties方法,发现里面第一步获取 @Autowired 和 @Value 注解的 成员变量 和 方法参数信息 的 InjectionMetadata 对象信息。我们可以通过 反射 获取 其中的信息

image-20230614112731102

1
2
3
4
5
6
7
8
9
10
// 通过 反射 获取方法 参数一:方法名-getDeclaredMethod 方法二-方法参数类-Class<?>... parameterTypes
Method findAutowiringMetadata = autowiredAnnotationBeanPostProcessor.getClass()
.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
// 由于 findAutowiringMetadata 方法 是由 private 修饰, 所以 设置可用
findAutowiringMetadata.setAccessible(true);
// 调用方法 参数一:调用者-autowiredAnnotationBeanPostProcessor 参数二:方法参数-args
// 获取 Bean1 上 @Autowired 和 @Value 注解的 成员变量 和 方法参数信息
InjectionMetadata metadata =
(InjectionMetadata) findAutowiringMetadata.invoke(autowiredAnnotationBeanPostProcessor, "beanReplica1", BeanReplica1.class, null);
logger.info("metadata: {}", metadata);

image-20230614113038993

调用 InjectionMetadata.inject 进行 依赖 注入

1
2
// 调用 inject 进行 依赖注入 注入时 按照 类型 查找
metadata.inject(beanReplica1, "beanReplica1", null);

image-20230614114100959

MetaData

image-20230614132136913

image-20230614131738276

Metadata.inject分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Test
public void testDoResolveDependency() throws Throwable {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 注册 Bean (参数一:bean 名称 参数二:实例化对象【不会进行创建过程,依赖注入】)
beanFactory.registerSingleton("beanReplica2", new BeanReplica2());
beanFactory.registerSingleton("beanReplica3", new BeanReplica3());
// 添加解析器
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 添加 ${} 解析器
beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

// 创建后处理器对象
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =
new AutowiredAnnotationBeanPostProcessor();
// 向 Bean 实例提供所属工厂的回调
autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);

BeanReplica1 beanReplica1 = new BeanReplica1();
logger.info("beanReplica1:{}", beanReplica1.toString());

// @Autowired 属性 注入 分析:metadata.inject 给 beanReplica1 注入 beanReplica3 的 过程
// 通过 Field 属性名 找到 属性成员变量类型 根据类型从容器中找到相应的Bean容器
Field fieldBeanReplica3 = BeanReplica1.class.getDeclaredField("beanReplica3");
// 将成员信息封装成 DependencyDescriptor 对象
DependencyDescriptor descriptorForBean3 = new DependencyDescriptor(fieldBeanReplica3, false);
// 从 beanFactory 容器中根据 类型 找到相应的容器
BeanReplica3 beanReplica3 = (BeanReplica3) beanFactory.doResolveDependency(descriptorForBean3, null, null, null);
logger.info("beanReplica3--->{}", beanReplica3);
// set 方法 注入
// 通过 Mothed 方法中的参数 找到参数类型 根据 参数类型从容器中找到相应的Bean容器
Method setBeanReplica2 = BeanReplica1.class.getDeclaredMethod("setBeanReplica2", BeanReplica2.class);
DependencyDescriptor descriptorForBean2 = new DependencyDescriptor(new MethodParameter(setBeanReplica2, 0), false);
BeanReplica2 beanReplica2 = (BeanReplica2) beanFactory.doResolveDependency(descriptorForBean2, null, null, null);
logger.info("beanReplica2---->{}", beanReplica2);
// @Value set 属性注入
Method setPort = beanReplica1.getClass().getDeclaredMethod("setPort", String.class);
DependencyDescriptor descriptorForString = new DependencyDescriptor(new MethodParameter(setPort, 0), false);
String port = (String) beanFactory.doResolveDependency(descriptorForString, null, null, null);
logger.info("port---->{}", port);
// 属性注入
beanReplica1.setBeanReplica2(beanReplica2);
beanReplica1.setBeanReplica3(beanReplica3);
beanReplica1.setPort(port);

logger.info("bean1:{}", beanReplica1.toString());
}

image-20230614140728363

BeanFactory后处理器

BeanFactory后处理器的作用

BeanFactory后处理器的作用:为 BeanFatory提供扩展,补充 Bean的定义

常见的BeanFactory后处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test
public void testBeanFactoryPostProcessor() {

GenericApplicationContext genericApplicationContext = new GenericApplicationContext();

genericApplicationContext.registerBean("config1", Config1.class);

// 添加 Bean 工厂 后处理器
// @Configuration @Bean @Import @ImportResource
genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class);

// @MapperSanner
genericApplicationContext.registerBean(
MapperScannerConfigurer.class,
db -> {
// 指定扫描 @Mapper 的包
db.getPropertyValues().add("basePackage", "com.example.demo.mapper");
}
);

// 初始化容器
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

genericApplicationContext.destroy();
}

BeanFactory后置处理器实现

@Component

简单实现

将 类上有 @Component 注解的注入到容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Test
public void testBeanFactoryPostProcessorDemo() throws IOException {

GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean("config1", Config1.class);

// 寻找 Config1 类中 ComponentScan 注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config1.class, ComponentScan.class);
if (componentScan != null) {
// 获取 ComponentScan 注解中的 basePackages 属性
for (String s : componentScan.basePackages()) {
// 将 basePackage 属性值转换为 路径: com.example.demo.component -> classpath*:com/example/demo/component/**/*.class
String path = "classpath*:" + s.replace(".", "/") + "/**/*.class";
// 根据 路径 获取 Resource 二进制资源
Resource[] resources = genericApplicationContext.getResources(path);

// 工厂 获取类的元信息
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
// Bean 名称generator
AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();


for (Resource resource : resources) {
MetadataReader metadataReader = factory.getMetadataReader(resource);
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

logger.info(
"类名:{}, 类上是否存在 @Component 注解:{}, 类上是否存在 @Component派生 注解:{} ",
metadataReader.getClassMetadata().getClassName(),
metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()),
metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())
);

// 如果 类上存在@Component 注解或者@Component派生 注解 则将其注入 容器 中
if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
// 构建 Bean 的定义
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
// 获取 Bean 名称
String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, genericApplicationContext.getDefaultListableBeanFactory());
// 根据 Bean定义 注入到 Bean容器 中
genericApplicationContext.registerBeanDefinition(beanName, beanDefinition);
}
}
}

// 初始化容器
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

// 销毁容器
genericApplicationContext.destroy();
}
}
BeanFactoryPostProcessor

通过 实现BeanFactory后置处理器接口,将 类上有 @Component 注解的注入到容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {

private static final Logger logger = LoggerFactory.getLogger(ComponentScanPostProcessor.class);

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

}

@Override
@SneakyThrows
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {

// 寻找 Config1 类中 ComponentScan 注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config1.class, ComponentScan.class);
if (componentScan != null) {
// 获取 ComponentScan 注解中的 basePackages 属性
for (String s : componentScan.basePackages()) {
// 将 basePackage 属性值转换为 路径: com.example.demo.component -> classpath*:com/example/demo/component/**/*.class
String path = "classpath*:" + s.replace(".", "/") + "/**/*.class";
// 根据 路径 获取 Resource 二进制资源
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);

// 工厂 获取类的元信息
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
// Bean 名称generator
AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();


for (Resource resource : resources) {
MetadataReader metadataReader = factory.getMetadataReader(resource);
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

logger.info(
"类名:{}, 类上是否存在 @Component 注解:{}, 类上是否存在 @Component派生 注解:{} ",
metadataReader.getClassMetadata().getClassName(),
metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()),
metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())
);

// 如果 类上存在@Component 注解或者@Component派生 注解 则将其注入 容器 中
if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
// 构建 Bean 的定义
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName())
.getBeanDefinition();
// 获取 Bean 名称
String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, beanFactory);
// 根据 Bean定义 注入到 Bean容器 中
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test
public void testBeanFactoryComponentPostProcessor() {

GenericApplicationContext genericApplicationContext = new GenericApplicationContext();

genericApplicationContext.registerBean("config1", Config1.class);

// 添加 Bean 工厂 后处理器
// @Configuration @Bean @Import @ImportResource
genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class);

// @MapperSanner
genericApplicationContext.registerBean(
MapperScannerConfigurer.class,
db -> {
// 指定扫描 @Mapper 的包
db.getPropertyValues().add("basePackage", "com.example.demo.mapper");
}
);

// 初始化容器
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

genericApplicationContext.destroy();
}

@Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class BeanPostProcessor implements BeanDefinitionRegistryPostProcessor {

private static final Logger logger = LoggerFactory.getLogger(BeanPostProcessor.class);

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

}

@Override
@SneakyThrows
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
// 获取 指定类的元信息
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
MetadataReader metadataReader =
factory.getMetadataReader(new ClassPathResource("com/example/demo/config/config1.class"));
// 获取类中 被@Bean注解修饰 的方法
Set<MethodMetadata> annotatedMethods =
metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());

annotatedMethods.forEach(method -> {
// 获取 @Bean 注解上的属性值 initMethod 即 初始化执行的方法
String initMethod =
(String) method.getAnnotationAttributes(Bean.class.getName()).get("initMethod");

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition()
.setFactoryMethodOnBean(method.getMethodName(), "config1")
// 指定自动装配模式 : AUTOWIRE_CONSTRUCTOR -> 根据 构造方法的参数 或者 工厂方法的参数 完成自动装配
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR)
.setInitMethodName(initMethod.length() > 0 ? initMethod : null)
.getBeanDefinition();
// 根据 Bean定义 注入到 Bean容器 中
beanFactory.registerBeanDefinition(method.getMethodName(), beanDefinition);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testBeanFactoryBeanPostProcessor() {
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean("config1", Config1.class);

genericApplicationContext.addBeanFactoryPostProcessor(new ComponentScanPostProcessor());
genericApplicationContext.addBeanFactoryPostProcessor(new BeanPostProcessor());

// 初始化容器
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

// 销毁容器
genericApplicationContext.destroy();
}

@Mapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

}

@Override
@SneakyThrows
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:com/example/demo/mapper/**/*.class");

CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();

AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();

for (Resource resource : resources) {
MetadataReader metadataReader = factory.getMetadataReader(resource);
// 判断指定类是否是 接口
if (metadataReader.getClassMetadata().isInterface()) {
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
.addConstructorArgValue(metadataReader.getClassMetadata().getClassName())
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
.getBeanDefinition();
// 从 元信息 中获取 beanName
String beanName = annotationBeanNameGenerator.generateBeanName(
BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition(),
beanFactory
);
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void testMapperFactoryBeanPostProcessor() {
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean("config1", Config1.class);

genericApplicationContext.addBeanFactoryPostProcessor(new ComponentScanPostProcessor());
genericApplicationContext.addBeanFactoryPostProcessor(new BeanPostProcessor());
genericApplicationContext.addBeanFactoryPostProcessor(new MapperPostProcessor());

// 初始化容器
genericApplicationContext.refresh();

Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println);

// 销毁容器
genericApplicationContext.destroy();
}

Aware和InitalizingBean

Aware 接口用于 注入 一些与容器相关信息:提供了一种内置的注入手段,可以注入BeanFactoryApplicationContext 等,Aware接口属于内置功能,不加任何的扩展即可使用,不存在失效的情况

InitalizingBean接口提供一种内置的初始化方法

内置的注入和初始化不受扩展功能的影响,总会被执行,因此Spring框架内部常用它们

  • BeanNameAware:注入 Bean名称
  • BeanFactoryAware:注入 BeanFactory 容器
  • ApplicationContextAware:注入 ApplicationContext 容器
  • EmbeddedValueResolverAware:注入 单个属性值 ${}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {

private static final Logger logger = LoggerFactory.getLogger(MyBean.class);

@Override
public void setBeanName(String name) {
logger.info("beanName:{}", name);
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
logger.info("applicationContext:{}", applicationContext);
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info("initializingBean");
}
}

image-20230709124800000

初始化和销毁

Spring提供了多种初始化和销毁的手段,它们有固定的执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CustomBean implements InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(CustomBean.class);

@PostConstruct
public void init() {
logger.info(" @PostConstruct 初始化");
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info(" InitializingBean接口 初始化");
}

public void initMethod() {
logger.info(" initMethod 初始化");
}

@PreDestroy
public void close() {
logger.info(" @PreDestroy 销毁");
}


public void disposeMethod() {
logger.info(" disposeMethod 销毁");
}

@Override
public void destroy() throws Exception {
logger.info(" DisposableBean接口 销毁");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootApplication
public class SpringDemoTestApplication {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {

Logger logger = LoggerFactory.getLogger(SpringDemoTestApplication.class);

ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args);
context.close();
}

@Bean(initMethod = "initMethod", destroyMethod = "disposeMethod")
public CustomBean customBean() {
return new CustomBean();
}

初始化:@PostConstruct -> InitializingBean 接口方法 -> @Bean属性值initMethod

销毁:@PreDestory -> DisposableBean 接口方法 -> @Bean属性值 disposeMethod

image-20230709174601195

Scope

Scope 类型

image-20230709130657301

image-20230709130805082

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class BeanForRequest implements InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(BeanForRequest.class);

@Override
public void destroy() throws Exception {
logger.info("销毁 BeanForRequest");
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info("初始化 BeanForRequest");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class BeanForApplication implements InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(BeanForApplication.class);

@Override
public void destroy() throws Exception {
logger.info("销毁 BeanForApplication");
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info("初始化 BeanForApplication");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class BeanForSession implements InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(BeanForSession.class);


@Override
public void destroy() throws Exception {
logger.info("销毁 BeanForSession");
}

@Override
public void afterPropertiesSet() throws Exception {
logger.info("初始化 BeanForSession");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RestController(value = "/scope")
public class ScopeController {

@Lazy
@Resource
private BeanForApplication beanForApplication;

@Lazy
@Resource
private BeanForRequest beanForRequest;

@Lazy
@Resource
private BeanForSession beanForSession;

@GetMapping("/test")
public String test() {
StringBuilder sb = new StringBuilder();
return sb.append("beanForRequest:" + beanForRequest).append("\n")
.append("beanForSession:" + beanForSession).append("\n")
.append("beanForApplication:" + beanForApplication).append("\n")
.toString();
}
}
  • 每次 HTTP 请求会产生一个新的 Bean,并在请求结束后销毁

  • 使用不同的浏览器维护着不同的 Session,因此使用不同的浏览器会产生不同的 BeanForSession 对象,该 Bean 在当前 HTTP Session 内有效,Session 过期后被销毁

  • 每个 Web 应用启动时创建一个 Bean 对象,该 Bean 在当前Serlvet Tomcat应用启动时间内有效

image-20230709171343040

Scope 失效分析

1
2
3
4
@Component
@Scope(value = SCOPE_PROTOTYPE)
public class F1 {
}
1
2
3
4
5
6
7
8
9
@Component
public class E {
@Resource
private F1 f1;

public F1 getF1() {
return f1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootApplication
public class SpringDemoTestApplication {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {

Logger logger = LoggerFactory.getLogger(SpringDemoTestApplication.class);
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args);
E bean = context.getBean(E.class);
logger.info("{}", bean.getF1());
logger.info("{}", bean.getF1());
logger.info("{}", bean.getF1());
}
}

image-20230709203305784

单例注入多例,Scoep 失效情况

对于 单列对象,依赖注入仅仅发生了一次,没有用到多例的F,因此 E 用的始终是第一次依赖注入的 F

image-20230709202948795

解决方式:

  • 使用 @Lazy 注解生成代理

  • @Scope注解中的proxyMode = ScopedProxyMode.TARGET_CLASS,生成代理

代理对象是同一个,但是每次使用代理对象任意方法时,有代理创建新的对象

  • 注入 ObjectFactory 工厂,从中获取多例对象
  • 注入 ApplicationContext 工厂,从中获取多例对象

image-20230709205729574

解决方法不同,但是原理一致,都是通过代理对象或者工厂推迟其他scope bean的获取