本章是《spring4.1.8扩展实战》的第七篇,我们来尝试在容器初始化的时候对bean实例做设置;
原文地址:https://blog.csdn.net/boling_cavalry/article/details/82250986

控制bean的两种扩展方式
两种方式可以对bean做控制(例如修改某个成员变量)
1. 改变bean的定义(BeanFactoryPostProcessor接口) ,可以想象成修改了class文件,这样实例化出来的每个对象都变了;
2. 只改变实例化的对象(BeanPostProcessor接口);

上述两种方式都能控制bean,第一种请参照《
spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)》,今天我们来研究第二种:改变实例化的对象;

本章概览
全文由以下部分组成:
1. spring源码分析,了解BeanPostProcessor接口的实现类如何被注册到spring容器;
2. spring源码分析,了解已经注册到spring环境的BeanPostProcessor实现类如何被使用;
3. 实战,开发一个BeanPostProcessor实现类,验证是否能用来改变指定的bean;

源码分析:BeanPostProcessor接口的实现类如何被注册到spring容器
从spring容器的初始化代码看起吧,看AbstractApplicationContext类的refresh方法,如下图所示,红框中的方法负责将BeanPostProcessor接口的实现类注册到spring容器:

展开registerBeanPostProcessors方法,发现是委托PostProcessorRegistrationDelegate类的静态方法registerBeanPostProcessors来完成注册工作的:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
1
2
3

3. 展开PostProcessorRegistrationDelegate.registerBeanPostProcessors方法,里面的代码逻辑简洁整齐,意图目的一目了然:

public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取所有实现BeanPostProcessor接口的bean的名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

//注意,此时尽管注册操作还没有开始,但是之前已经有一些特殊的bean已经注册进来了,
//详情请看AbstractApplicationContext类的prepareBeanFactory方法,
//因此getBeanPostProcessorCount()方法返回的数量并不为零,
//加一是因为方法末尾会注册一个ApplicationListenerDetector接口的实现类
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
//这里的BeanPostProcessorChecker也是个BeanPostProcessor的实现类,用于每个bean的初始化完成后,做一些简单的检查
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

//如果这些bean还实现了PriorityOrdered接口(在意执行顺序),就全部放入集合priorityOrderedPostProcessors
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
//集合internalPostProcessors,用来存放同时实现了PriorityOrdered和MergedBeanDefinitionPostProcessor接口的bean
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
//集合orderedPostProcessorNames用来存放实现了Ordered接口的bean的名称(在意执行顺序)
List<String> orderedPostProcessorNames = new ArrayList<String>();
//集合nonOrderedPostProcessorNames用来存放即没实现PriorityOrdered接口,也没有实现Ordered接口的bean的名称(不关心执行顺序)
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
//实现了PriorityOrdered接口的bean,都放入集合priorityOrderedPostProcessors
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
//实现了MergedBeanDefinitionPostProcessor接口的bean,都放入internalPostProcessors集合
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
//实现了Ordered接口的bean,将其名称都放入orderedPostProcessorNames集合
orderedPostProcessorNames.add(ppName);
}
else {
//既没实现PriorityOrdered接口,也没有实现Ordered接口的bean,将其名称放入nonOrderedPostProcessorNames集合
nonOrderedPostProcessorNames.add(ppName);
}
}

//实现了PriorityOrdered接口的bean排序
OrderComparator.sort(priorityOrderedPostProcessors);
//注册到容器
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
//处理所有实现了Ordered接口的bean
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
//前面将所有实现了PriorityOrdered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors,
//此处将所有实现了Ordered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}

//实现了Ordered接口的bean排序
OrderComparator.sort(orderedPostProcessors);
//注册到容器
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
//此处将其余实现了MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//注册到容器
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

OrderComparator.sort(internalPostProcessors);
//将所有实现了MergedBeanDefinitionPostProcessor接口的bean也注册到容器
registerBeanPostProcessors(beanFactory, internalPostProcessors);
//创建一个ApplicationListenerDetector对象并且注册到容器,这就是前面计算beanProcessorTargetCount的值时加一的原因
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
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
以上代码已加注释,就不多解读了,有一点需要注意:对于实现了MergedBeanDefinitionPostProcessor接口的bean,在前面几次调用registerBeanPostProcessors方法的时候已经注册过了,那么在最后执行的registerBeanPostProcessors(beanFactory, internalPostProcessors),岂不是将一个bean注册了多次?

为了弄清楚这个问题需要看registerBeanPostProcessors方法:

private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

for (BeanPostProcessor postProcessor : postProcessors) {
//对每个bean都调用beanFactory.addBeanPostProcessor方法来注册
beanFactory.addBeanPostProcessor(postProcessor);
}
}
1
2
3
4
5
6
7
8

addBeanPostProcessor方法的代码在AbstractApplicationContext类中,如下所示,先删除再添加,这样反复注册也没有问题:

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
//如果已经注册,就先删除掉
this.beanPostProcessors.remove(beanPostProcessor);
//再注册
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

至此,我们已经弄清楚了BeanPostProcessor实现类的bean注册到spring容器的逻辑,接下来看看spring容器如何使用这些bean;

源码分析,BeanPostProcessor实现类如何被使用
要弄清楚BeanPostProcessor接口的实现类是在哪里被用到的,还是从负责容器初始化的AbstractApplicationContext类的refresh方法看起,如下图红框中的finishBeanFactoryInitialization方法,就是负责实例化和初始化bean的:

从finishBeanFactoryInitialization方法到BeanPostProcessor的实现类被使用,中间有多层逻辑和调用,篇幅所限就不逐个展开了,直接列出堆栈信息,您可以根据此信息去查看对应源码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean()
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject()
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton()
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean()
org.springframework.beans.factory.support.AbstractBeanFactory.getBean()
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons()
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization()
org.springframework.context.support.AbstractApplicationContext.refresh()
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh()
org.springframework.boot.SpringApplication.refresh()
org.springframework.boot.SpringApplication.refreshContext()
org.springframework.boot.SpringApplication.run()
org.springframework.boot.SpringApplication.run()
org.springframework.boot.SpringApplication.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

3. 根据上述堆栈信息,直接查看AbstractAutowireCapableBeanFactory类的initializeBean()方法:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//对已经实例化的bean,在初始化前用BeanPostProcessor实现类去处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
//bean的初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}

if (mbd == null || !mbd.isSynthetic()) {
//对已经实例化的bean,在初始化后用BeanPostProcessor实现类去处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
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
如上所示,我们最关注的代码是applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization这两个方法,它们分别在bean的初始化方法invokeInitMethods的前后被执行;

4. 先看看applyBeanPostProcessorsBeforeInitialization方法,逻辑非常简单,就是取出所有已注册的BeanPostProcessor实现类,执行其postProcessBeforeInitialization方法,入参是当前正在做实例化和初始化的bean实例:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
//逐一执行每个BeanPostProcessor实现类的postProcessBeforeInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

5. 在invokeInitMethods方法执行完毕后会执行applyBeanPostProcessorsAfterInitialization方法,代码如下,与applyBeanPostProcessorsBeforeInitialization如出一辙,仅有的不同是调用的beanProcessor的方法变成了postProcessAfterInitialization:

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
//逐一执行每个BeanPostProcessor实现类的postProcessAfterInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
以上就是spring容器初始化过程中对BeanPostProcessor实现类的使用场景,此时还剩一点疑问需要澄清:在分析注册过程的时候,曾看到实现MergedBeanDefinitionPostProcessor接口的bean是最后注册的,那么这些MergedBeanDefinitionPostProcessor实现类在spring容器中是何处使用的呢?
为了搞清这个问题,来看看AbstractAutowireCapableBeanFactory类的doCreateBean方法,前面我们分析的initializeBean方法就是在这里面被调用的:

如上图所示,红框中就是用所有MergedBeanDefinitionPostProcessor实现类去处理当前正在实例化的bean,然后才会执行绿框中的initializeBean方法(里面是我们刚才分析的bean的初始化,BeanPostProcessor实现类被使用的逻辑);
来看看红框中的applyMergedBeanDefinitionPostProcessors方法,主要目的是处理特殊的合成bean的定义类:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
throws BeansException {

try {
//取出每个注册的BeanPostProcessor实现类
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//只有实现了MergedBeanDefinitionPostProcessor接口才执行
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
//执行postProcessMergedBeanDefinition
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
catch (Exception ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing failed of bean type [" + beanType + "] failed", ex);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

至此,我们对BeanPostProcessor有关的源码分析就完成了,小结一下:
1. 初始化时,spring容器有特别处理,会直接调用beanFactory.addBeanPostProcessor进行注册(例如AbstractApplicationContext类的prepareBeanFactory方法中就有);
2. 找出所有实现了BeanPostProcessor接口的bean,注册到容器,注册顺序如下:
第一:实现了PriorityOrdered接口的,排序后;
第二:实现了Ordered接口的,排序后;
第三:既没实现PriorityOrdered接口,也没有实现Ordered接口的;
第四:实现了MergedBeanDefinitionPostProcessor接口的(这些也按照PriorityOrdered、Ordered等逻辑拍过续);
第五:实例化一个ApplicationListenerDetector对象;
3. 实例化bean的时候,对于每个bean,先用MergedBeanDefinitionPostProcessor实现类的postProcessMergedBeanDefinition方法处理每个bean的定义类;
4. 再用BeanPostProcessor的postProcessBeforeInitialization方法处理每个bean实例;
5. bean实例初始化;
6. 用BeanPostProcessor的postProcessAfterInitialization方法处理每个bean实例;

源码分析结束,接下来自定义一个BeanPostProcessor实现类,验证我们之前的分析:控制bean实例;

实战自定义BeanPostProcessor实现类
本次实战的内容是创建一个springboot工程,在里面自定义一个BeanPostProcessor接口的实现类,如果您不想敲代码,也可以去github下载源码,地址和链接信息如下表所示:

名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
这个git项目中有多个文件夹,本章源码在文件夹customizebeanpostprocessor下,如下图红框所示:

接下来开始实战吧:
1. 基于maven创建一个springboot的web工程,名为customizebeanpostprocessor,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.bolingcavalry</groupId>
<artifactId>customizebeanpostprocessor</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>customizebeanpostprocessor</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.15.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
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

2. 创建Utils.java,里面有一些静态的工具方法,例如打印当前堆栈:

package com.bolingcavalry.customizebeanpostprocessor.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Utils {

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

/**
* 打印当前线程堆栈信息
* @param prefix
*/
public static void printTrack(String prefix){
StackTraceElement[] st = Thread.currentThread().getStackTrace();

if(null==st){
logger.info("invalid stack");
return;
}

StringBuffer sbf =new StringBuffer();

for(StackTraceElement e:st){
if(sbf.length()>0){
sbf.append(" <- ");
sbf.append(System.getProperty("line.separator"));
}

sbf.append(java.text.MessageFormat.format("{0}.{1}() {2}"
,e.getClassName()
,e.getMethodName()
,e.getLineNumber()));
}

logger.info(prefix
+ "\n************************************************************\n"
+ sbf.toString()
+ "\n************************************************************");
}
}
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

3. 创建接口CalculateService,定义了几个方法:

package com.bolingcavalry.customizebeanpostprocessor.service;

public interface CalculateService {
/**
* 整数加法
* @param a
* @param b
* @return
*/
int add(int a, int b);

/**
* 返回当前实现类的描述信息
* @return
*/
String getServiceDesc();

/**
* 设置当前实现类的描述信息
* @return
*/
void setServiceDesc(String serviceDesc);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

4. 创建CalculateService的实现类CalculateServiceImpl,并且用@Service注解将定义为spring的bean:

package com.bolingcavalry.customizebeanpostprocessor.service.impl;

import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import org.springframework.stereotype.Service;

@Service("calculateService")
public class CalculateServiceImpl implements CalculateService {

private String serviceDesc = "desc from class";

@Override
public int add(int a, int b) {
return a + b;
}

@Override
public String getServiceDesc() {
return serviceDesc;
}

@Override
public void setServiceDesc(String serviceDesc) {
this.serviceDesc = serviceDesc;
}
}
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
注意该类的成员变量serviceDesc,值已经固定为”desc from class”;

5. 创建Controller类HelloController,在响应web请求的时候,会用到calculateService提供的服务:

package com.bolingcavalry.customizebeanpostprocessor.controller;

import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Autowired(required = false)
CalculateService calculateService;

@GetMapping("/add/{a}/{b}")
public String add(@PathVariable("a") int a, @PathVariable("b") int b){
return "add result : " + calculateService.add(a, b) + ", from [" + calculateService.getServiceDesc() + "]";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如上所示,正常情况下,web响应为”add result : x, from [desc from class]”,这个desc from class,就是CalculateServiceImpl的成员变量serviceDesc的值;

6. 创建BeanPostProcessor的实现类CustomizeBeanPostProcessor,这里面会修改calculateService实例的成员变量serviceDesc的值,记得用注解@Component将其设置为bean:

package com.bolingcavalry.customizebeanpostprocessor.processor;

import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import com.bolingcavalry.customizebeanpostprocessor.util.Utils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class CustomizeBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("calculateService".equals(beanName)) {
//打印当前堆栈
Utils.printTrack("do postProcess before initialization");
CalculateService calculateService = (CalculateService)bean;
//修改calculateService实例的成员变量serviceDesc的值
calculateService.setServiceDesc("desc from " + this.getClass().getSimpleName());
}
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("calculateService".equals(beanName)) {
//打印当前堆栈
Utils.printTrack("do postProcess after initialization");
}
return 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

7. 启动应用,在启动日志中可以看到CustomizeBeanPostProcessor实例的两个方法被调用时打印的堆栈日志,和之前我们分析的源码是一致的:

2018-09-02 18:35:53.618 INFO 22520 --- [ main] c.b.c.util.Utils : do postProcess before initialization
************************************************************
java.lang.Thread.getStackTrace() 1,559 <-
com.bolingcavalry.customizebeanpostprocessor.util.Utils.printTrack() 15 <-
com.bolingcavalry.customizebeanpostprocessor.processor.CustomizeBeanPostProcessor.postProcessBeforeInitialization() 14 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization() 409 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,626 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 555 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 202 <-
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate() 208 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency() 1,138 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency() 1,066 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject() 585 <-
org.springframework.beans.factory.annotation.InjectionMetadata.inject() 88 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues() 366 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean() 1,272 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 553 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 197 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 761 <-
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 867 <-
org.springframework.context.support.AbstractApplicationContext.refresh() 543 <-
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh() 122 <-
org.springframework.boot.SpringApplication.refresh() 693 <-
org.springframework.boot.SpringApplication.refreshContext() 360 <-
org.springframework.boot.SpringApplication.run() 303 <-
org.springframework.boot.SpringApplication.run() 1,118 <-
org.springframework.boot.SpringApplication.run() 1,107 <-
com.bolingcavalry.customizebeanpostprocessor.CustomizebeanpostprocessorApplication.main() 10
************************************************************
2018-09-02 18:35:53.619 INFO 22520 --- [ main] c.b.c.util.Utils : do postProcess after initialization
************************************************************
java.lang.Thread.getStackTrace() 1,559 <-
com.bolingcavalry.customizebeanpostprocessor.util.Utils.printTrack() 15 <-
com.bolingcavalry.customizebeanpostprocessor.processor.CustomizeBeanPostProcessor.postProcessAfterInitialization() 24 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization() 423 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,638 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 555 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 202 <-
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate() 208 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency() 1,138 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency() 1,066 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject() 585 <-
org.springframework.beans.factory.annotation.InjectionMetadata.inject() 88 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues() 366 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean() 1,272 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 553 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 197 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 761 <-
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 867 <-
org.springframework.context.support.AbstractApplicationContext.refresh() 543 <-
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh() 122 <-
org.springframework.boot.SpringApplication.refresh() 693 <-
org.springframework.boot.SpringApplication.refreshContext() 360 <-
org.springframework.boot.SpringApplication.run() 303 <-
org.springframework.boot.SpringApplication.run() 1,118 <-
org.springframework.boot.SpringApplication.run() 1,107 <-
com.bolingcavalry.customizebeanpostprocessor.CustomizebeanpostprocessorApplication.main() 10
************************************************************
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

8. 在浏览器访问地址:http://localhost:8080/add/1/2,可以看到响应如下图所示,calculateService的成员变量serviceDesc的值已经被CustomizeBeanPostProcessor改为desc from CustomizeBeanPostProcessor:

至此,本次实战就完成了,从spring源码分析再到动手实战,我们对BeanPostProcessor的扩展有了更深入的认识,也希望这种扩展能帮助您更好的控制bean实例为业务需求服务;
---------------------
作者:博陵精骑
来源:CSDN
原文:https://blog.csdn.net/boling_cavalry/article/details/82250986
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://www.cnblogs.com/xiaobaoTribe/p/10708946.html

spring4.1.8扩展实战之七:控制bean(BeanPostProcessor接口)相关推荐

  1. 【嵌入式Linux】嵌入式项目实战之七步从零编写带GUI的应用之显示系统、输入系统、文字系统

    文章目录 前言 1.显示系统 1.1.程序分层 1.2.几个重要的数据结构 1.3.程序分析 2.输入系统 2.1.程序分层 2.2.触摸屏输入 2.2.1.几个重要的数据结构 2.2.1.程序分析 ...

  2. Spring系列第20篇:@Conditional通过条件来控制bean的注册

    面试阿里p7被问到的问题(当时我只知道第一个): @Conditional是做什么的? @Conditional多个条件是什么逻辑关系? 条件判断在什么时候执行? ConfigurationCondi ...

  3. SpringBoot如何正确控制bean的加载顺序

    1. 为什么需要控制bean的加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了SPI[Service Provider Interface]机 ...

  4. Spring 使用注解@DependsOn控制Bean加载顺序

    文章目录 1. 前言 2. 代码实现 1. 前言 默认情况下,Spring加载Bean的顺序是不确定的(或者可以理解为,按编译后的class文件顺序加载).当我们需要控制Bean加载顺序以满足特定的需 ...

  5. 云计算开发教程:Python自动化运维开发实战流程控制

    今天这篇文章是给大家分享一些云计算开发教程,今天讲解的是:Python自动化运维开发实战流程控制. Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. P ...

  6. azure vnc控制台_使用扩展和标签控制Azure成本

    azure vnc控制台 Depending on our design and security, we can create functions or use built-in tools to ...

  7. Spring控制Bean加载顺序

    spring容器载入bean顺序是不确定的,spring框架没有约定特定顺序逻辑规范. 首先要了解depends-on或@DependsOn作用,是用来表示一个bean A的实例化依赖另一个bean ...

  8. 【FPGA基础快速入门6】实战-----触摸按键控制LED灯的学习

    [FPGA基础快速入门6]实战-----触摸按键控制LED灯的学习 触摸按键的种类 触摸按键主要可以分为四大类: 电阻式.电容式.红外感应式以及表面声波式. 1.电阻式触摸按键又多块导电薄膜按照按键的 ...

  9. [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

    这是一篇系列博文.请关注我,学习更多.NET MAUI开发知识! [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构 [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互 [MAU ...

  10. 05【Verilog实战】AMBA 3 APB接口设计(附源码RTL/TB)

    官方手册:点击下载 脚  本:makefile 工  具:vcs & verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序 ...

最新文章

  1. ECSHOP 数据库结构说明
  2. 2050 Programming Competition (CCPC)
  3. php中bc,php中BC高精确度函数库
  4. 浪潮云海OS C位出道,融合开放基础设施呼之欲出
  5. mysql 8.0以上 新版本账号密码策略修改和密码修改
  6. 【形状检测】基于matlab Hough变换形状检测【含Matlab源码 468期】
  7. 杭电HDUacm2098
  8. 2020云课堂智慧职教答案计算机,2020云课堂智慧职教答案英语,云智慧职教题库,智慧职教测试答案...
  9. Linux I2C 驱动实验
  10. 英文版-Plan9汇编器-A Manual for the Plan 9 assembler
  11. 毕业一年后,我为什么选择去香港做IT?
  12. NOIP 提高组 飞扬的小鸟
  13. Android studio Android源码开发环境搭建
  14. The project seems to require yarn but it‘s not installed解决办法
  15. ABR与ASBR是什么?区别又是什么?
  16. 使用Python对xlsx,csv, txt格式文件进行读、写并绘图
  17. node.js常用模块
  18. 计算机维护宝典,分分钟教你“修电脑”的宝典,值得收藏
  19. Python调用Geopandas包矢量化txt点数据为shp数据
  20. Python Excel处理脚本

热门文章

  1. php解决中文乱码的函数,php 中解决json中文乱码的函数_PHP教程
  2. 手机电脑投屏软件_手机投屏电脑,电脑控制手机,推荐这款良心免费的软件
  3. python 多行缩进_【python cookbook】改变多行文本字符串的缩进
  4. java selenium2_Selenium2(webdirver)入门之环境搭建(Java版)
  5. 数据集:两种形式的铁离子在不同剂量下在动物体内的存留量
  6. php想做一个无刷新弹窗,php+ajax实现无刷新的新闻留言系统
  7. python中字符a如何变成b_python 如何把'a=b'这样的字符解析成dict类型
  8. java redis 字节_Redis Java
  9. 广金计算机网络有限公司怎么样,广东金融学院到底怎么样!?
  10. Python人脸识别之——创建csv文件 create_csv.py 代码 Python3.7