BeanFactoryPostProcessor:
官方类的注释
**
* Factory hook that allows for custom modification of an application context's
* bean definitions, adapting the bean property values of the context's underlying
* bean factory.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context. See
* {@link PropertyResourceConfigurer} and its concrete implementations for
* out-of-the-box solutions that address such configuration needs.
*
* <p>A {@code BeanFactoryPostProcessor} may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* <h3>Registration</h3>
* <p>An {@code ApplicationContext} auto-detects {@code BeanFactoryPostProcessor}
* beans in its bean definitions and applies them before any other beans get created.
* A {@code BeanFactoryPostProcessor} may also be registered programmatically
* with a {@code ConfigurableApplicationContext}.
*
* <h3>Ordering</h3>
* <p>{@code BeanFactoryPostProcessor} beans that are autodetected in an
* {@code ApplicationContext} will be ordered according to
* {@link org.springframework.core.PriorityOrdered} and
* {@link org.springframework.core.Ordered} semantics. In contrast,
* {@code BeanFactoryPostProcessor} beans that are registered programmatically
* with a {@code ConfigurableApplicationContext} will be applied in the order of
* registration; any ordering semantics expressed through implementing the
* {@code PriorityOrdered} or {@code Ordered} interface will be ignored for
* programmatically registered post-processors. Furthermore, the
* {@link org.springframework.core.annotation.Order @Order} annotation is not
* taken into account for {@code BeanFactoryPostProcessor} beans.
*
1.允许自定义修改应用程序上下文的bean定义,调整上下文底层的bean属性值。
2.对于针对系统管理员的自定义配置文件非常有用,重写在应用程序上下文中配置的bean属性。查看{@link PropertyResourceConfigurer}及其具体实现,解决此类配置需求的现成解决方案。
3.一个可以与bean交互并修改bean定义,但从来没有bean实例。如果bean过早的实例化,违反容器并导致意外的副作用。*如果需要bean实例交互,请考虑实现*改为{@link beanoptprocessor}。
4.注册{@code ApplicationContext}自动检测{@code BeanFactoryPostProcessor}并在创建任何其他bean之前应用它们。*{@code BeanFactoryPostProcessor}也可以通过编程方式注册*使用{@code ConfigurableApplicationContext}。
5.订购{@code BeanFactoryPostProcessor}在*{@code ApplicationContext}将根据*{@链接org.springframework.core.PriorityOrdered}和*{@链接org.springframework.core.Ordered}语义自动检测;。相反,*{@code BeanFactoryPostProcessor}以编程方式注册的bean使用{@code ConfigurableApplicationContext}将按以下顺序应用注册;通过实现的{@code PriorityOrdered}或{@code Ordered}接口将被忽略以编程方式注册的后处理器。此外{@链接org.springframework.core.注释.顺序@Order}注释不是考虑{@codebeanfactorypostprocessor}bean。
方法:postProcessBeanFactory的注释
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
.根据应用程序上下文的标准修改应用程序上下文的内部bean工厂初始化。所有bean定义都将被加载,但没有bean将被实例化。这允许重写或添加属性,甚至急于初始化bean。
--------------以上译文源于百度翻译
简而言之就是spring启动过程中,bean工厂创建完成以后,并把所有加载的bean定义写入bean工厂,此时bean工厂中只有bean的定义信息,没有实例化;可以通过实现BeanFactoryPostProcessor接口,来修改bean信息,也可以提前实例化bean修改属性;但是官方不建议这么做,如果bean过早的实例化,违反容器并导致意外的副作用。*如果需要bean实例交互,请考虑实现*改为{@link beanoptprocessor}。
下面只是一个demo,暂不考虑副作用等;
Demo:
自定义的MyBeanFactoryPostProcessor类实现BeanFactoryPostProcessor接口,并重写postProcessBeanFactory方法
package com.ppc.spring;
import com.ppc.spring.controller.UserController;
import com.ppc.spring.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("*****获取UserController对象*****");
UserController userController = (UserController) configurableListableBeanFactory.getBean("userController");
System.out.println("*****创建UserService对象*****");
UserService userService = new UserService(); //这里只为演示,创建一个UserService对象
System.out.println("*****给userController设置userService属性*****");
userController.setUserService(userService);//给userController赋值,等spring启动完成查看userController是否有userService对象
}
}
UserController类
package com.ppc.spring.controller;
import com.ppc.spring.service.UserService;
public class UserController {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public UserController() {
System.out.println(" UserController 构造函数");
}
public void execute(){
}
@Override
public String toString() {
return "UserController{" +
"userService=" + userService +
'}';
}
}
UserService类
package com.ppc.spring.service;
public class UserService {
public UserService() {
System.out.println("UserService 构造函数");
}
@Override
public String toString() {
return "UserService{}";
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userController" class="com.ppc.spring.controller.UserController"></bean>
<bean id="myFactoryBeanProcessor" class="com.ppc.spring.MyBeanFactoryPostProcessor"></bean>
</beans>
测试类:
package com.ppc.spring;
import com.ppc.spring.controller.UserController;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("springmvc.xml");
UserController userController = classPathXmlApplicationContext.getBean("userController", UserController.class);
System.out.println(userController);
}
}
测试结果:
G:\software\jdk\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar=3575:G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\bin" -Dfile.encoding=UTF-8 -classpath "G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar;G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\plugins\junit\lib\junit-rt.jar;G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\plugins\junit\lib\junit5-rt.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-launcher\1.6.2\junit-platform-launcher-1.6.2.jar;C:\Users\ppc\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-engine\1.6.2\junit-platform-engine-1.6.2.jar;C:\Users\ppc\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-commons\1.6.2\junit-platform-commons-1.6.2.jar;G:\software\jdk\jre\lib\charsets.jar;G:\software\jdk\jre\lib\deploy.jar;G:\software\jdk\jre\lib\ext\access-bridge-64.jar;G:\software\jdk\jre\lib\ext\cldrdata.jar;G:\software\jdk\jre\lib\ext\dnsns.jar;G:\software\jdk\jre\lib\ext\jaccess.jar;G:\software\jdk\jre\lib\ext\jfxrt.jar;G:\software\jdk\jre\lib\ext\localedata.jar;G:\software\jdk\jre\lib\ext\nashorn.jar;G:\software\jdk\jre\lib\ext\sunec.jar;G:\software\jdk\jre\lib\ext\sunjce_provider.jar;G:\software\jdk\jre\lib\ext\sunmscapi.jar;G:\software\jdk\jre\lib\ext\sunpkcs11.jar;G:\software\jdk\jre\lib\ext\zipfs.jar;G:\software\jdk\jre\lib\javaws.jar;G:\software\jdk\jre\lib\jce.jar;G:\software\jdk\jre\lib\jfr.jar;G:\software\jdk\jre\lib\jfxswt.jar;G:\software\jdk\jre\lib\jsse.jar;G:\software\jdk\jre\lib\management-agent.jar;G:\software\jdk\jre\lib\plugin.jar;G:\software\jdk\jre\lib\resources.jar;G:\software\jdk\jre\lib\rt.jar;D:\CODE\MAYUN\spring-source-analysis\target\test-classes;D:\CODE\MAYUN\spring-source-analysis\target\classes;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.3.0.RELEASE\spring-boot-starter-web-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter\2.3.0.RELEASE\spring-boot-starter-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot\2.3.0.RELEASE\spring-boot-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.0.RELEASE\spring-boot-autoconfigure-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.3.0.RELEASE\spring-boot-starter-logging-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\ppc\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\ppc\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.2\log4j-to-slf4j-2.13.2.jar;C:\Users\ppc\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.2\log4j-api-2.13.2.jar;C:\Users\ppc\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\ppc\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\ppc\.m2\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.3.0.RELEASE\spring-boot-starter-json-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.11.0\jackson-databind-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.0\jackson-annotations-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.11.0\jackson-core-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.0\jackson-datatype-jdk8-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.0\jackson-datatype-jsr310-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.0\jackson-module-parameter-names-2.11.0.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.0.RELEASE\spring-boot-starter-tomcat-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.35\tomcat-embed-core-9.0.35.jar;C:\Users\ppc\.m2\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;C:\Users\ppc\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.35\tomcat-embed-websocket-9.0.35.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-web\5.2.6.RELEASE\spring-web-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-beans\5.2.6.RELEASE\spring-beans-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-webmvc\5.2.6.RELEASE\spring-webmvc-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-aop\5.2.6.RELEASE\spring-aop-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-context\5.2.6.RELEASE\spring-context-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-expression\5.2.6.RELEASE\spring-expression-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\pdfbox\1.8.16\pdfbox-1.8.16.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\fontbox\1.8.16\fontbox-1.8.16.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\jempbox\1.8.16\jempbox-1.8.16.jar;C:\Users\ppc\.m2\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;C:\Users\ppc\.m2\repository\com\itextpdf\itextpdf\5.5.11\itextpdf-5.5.11.jar;C:\Users\ppc\.m2\repository\com\itextpdf\itext-asian\5.2.0\itext-asian-5.2.0.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.3.0.RELEASE\spring-boot-starter-test-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-test\2.3.0.RELEASE\spring-boot-test-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.3.0.RELEASE\spring-boot-test-autoconfigure-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\ppc\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\ppc\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\ppc\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\ppc\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\ppc\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;C:\Users\ppc\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;C:\Users\ppc\.m2\repository\org\assertj\assertj-core\3.16.1\assertj-core-3.16.1.jar;C:\Users\ppc\.m2\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter\5.6.2\junit-jupiter-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.6.2\junit-jupiter-api-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.6.2\junit-jupiter-params-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.6.2\junit-jupiter-engine-5.6.2.jar;C:\Users\ppc\.m2\repository\org\mockito\mockito-core\3.3.3\mockito-core-3.3.3.jar;C:\Users\ppc\.m2\repository\net\bytebuddy\byte-buddy\1.10.10\byte-buddy-1.10.10.jar;C:\Users\ppc\.m2\repository\net\bytebuddy\byte-buddy-agent\1.10.10\byte-buddy-agent-1.10.10.jar;C:\Users\ppc\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\ppc\.m2\repository\org\mockito\mockito-junit-jupiter\3.3.3\mockito-junit-jupiter-3.3.3.jar;C:\Users\ppc\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\ppc\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-core\5.2.6.RELEASE\spring-core-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-jcl\5.2.6.RELEASE\spring-jcl-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-test\5.2.6.RELEASE\spring-test-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\xmlunit\xmlunit-core\2.7.0\xmlunit-core-2.7.0.jar;C:\Users\ppc\.m2\repository\org\bouncycastle\bcpkix-jdk15on\1.64\bcpkix-jdk15on-1.64.jar;C:\Users\ppc\.m2\repository\org\bouncycastle\bcprov-jdk15on\1.64\bcprov-jdk15on-1.64.jar;C:\Users\ppc\.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit5 com.ppc.spring.SpringTest,test
00:15:08.007 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@55a1c291
00:15:08.164 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from class path resource [springmvc.xml]
00:15:08.192 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myFactoryBeanProcessor'
*****获取UserController对象*****
00:15:08.206 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userController'
UserController 构造函数
*****创建UserService对象*****
UserService 构造函数
*****给userController设置userService属性*****
00:15:08.208 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanProcessor'
UserController{userService=UserService{}}
Process finished with exit code 0
最后获取的对象UserController的属性userService是有值的
BeanPostProcessor
官方注释
* Factory hook that allows for custom modification of new bean instances —
* for example, checking for marker interfaces or wrapping beans with proxies.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement {@link #postProcessBeforeInitialization},
* while post-processors that wrap beans with proxies will normally
* implement {@link #postProcessAfterInitialization}.
*
* <h3>Registration</h3>
* <p>An {@code ApplicationContext} can autodetect {@code BeanPostProcessor} beans
* in its bean definitions and apply those post-processors to any beans subsequently
* created. A plain {@code BeanFactory} allows for programmatic registration of
* post-processors, applying them to all beans created through the bean factory.
*
* <h3>Ordering</h3>
* <p>{@code BeanPostProcessor} beans that are autodetected in an
* {@code ApplicationContext} will be ordered according to
* {@link org.springframework.core.PriorityOrdered} and
* {@link org.springframework.core.Ordered} semantics. In contrast,
* {@code BeanPostProcessor} beans that are registered programmatically with a
* {@code BeanFactory} will be applied in the order of registration; any ordering
* semantics expressed through implementing the
* {@code PriorityOrdered} or {@code Ordered} interface will be ignored for
* programmatically registered post-processors. Furthermore, the
* {@link org.springframework.core.annotation.Order @Order} annotation is not
* taken into account for {@code BeanPostProcessor} beans.
1.允许自定义修改新bean实例&mdash的工厂钩子;*例如,检查标记接口或用代理包装bean。
2.典型地,通过标记接口填充bean的后处理器*或类似的方法将实现{@link #postProcessBeforeInitialization},*而用代理包装bean的后处理器将正常运行*实现{@link #postProcessAfterInitialization}。**
3.注册一个{@code ApplicationContext}可以自动检测{@code BeanPostProcessor} bean*在它的bean定义中,然后将这些后处理程序应用到任何bean*创建。一个普通的{@code BeanFactory}允许编程注册*后处理器,将它们应用到通过bean工厂创建的所有bean。
4.排序*{@code BeanPostProcessor}自动检测到的bean* {@code ApplicationContext}将根据* {@link org.springframework.core。PriorityOrdered},* {@link org.springframework.core。命令}语义。相比之下,通过编程方式注册的bean* {@code BeanFactory}将按注册顺序申请;任何订购的实现所表达的语义* {@code PriorityOrdered}或{@code Ordered}接口将被忽略以编程方式注册后处理器。此外,* {@link org.springframework.core.annotation。Order @Order}注释不是*考虑了{@code BeanPostProcessor} bean。
方法:
/**
* Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/ * **将此{@code BeanPostProcessor}应用到给定的新bean实例,先于任何bean*初始化回调(如InitializingBean的{@code afterPropertiesSet})*或自定义的init方法)。bean已经填充了属性值。返回的bean实例可能是原始bean的包装器。默认实现按原样返回给定的{@code bean}。@param bean新bean实例豆子的名字* @返回要使用的bean实例,原始的或包装好的bean实例;*如果{@code null},则不会调用后续的beanpostprocessor* @throws org.springframework.beans。BeansException在错误的情况下* @see org.springframework.beans.factory.InitializingBean # afterPropertiesSet* /
/**
* Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other {@code BeanPostProcessor} callbacks.
* <p>The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
*将此{@code BeanPostProcessor}应用到给定的新bean实例后的任何bean*初始化回调(如InitializingBean的{@code afterPropertiesSet})*或自定义的init方法)。bean已经填充了属性值。返回的bean实例可能是原始bean的包装器。对于FactoryBean,这个回调将同时为FactoryBean调用实例和由FactoryBean创建的对象(从Spring 2.0开始)。的后处理器可以决定是应用到FactoryBean还是创建的对象或通过相应的{@code bean instanceof FactoryBean}检查两者。这个回调也将在a触发短路后被调用* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}方法,*与所有其他{@code BeanPostProcessor}回调相反。默认实现按原样返回给定的{@code bean}。@param bean新bean实例豆子的名字* @返回要使用的bean实例,原始的或包装好的bean实例;*如果{@code null},则不会调用后续的beanpostprocessor* @throws org.springframework.beans。BeansException在错误的情况下* @see org.springframework.beans.factory.InitializingBean # afterPropertiesSet* @see org.springframework.beans.factory.FactoryBean
简而言之就是before方法在bean实例化后初始化前使用,after方法在初始化后使用,都可以修改bean对象
Demo:
MyBeanPostProcessor类实现BeanPostProcessor接口,重写两个方法
package com.ppc.spring;
import com.ppc.spring.entity.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(!"user".equals(beanName)) return bean;
System.out.println("***********MyBeanPostProcessor before processor****************");
User user = (User)bean;
user.setName("peter");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(!"user".equals(beanName)) return bean;
System.out.println("***********MyBeanPostProcessor after processor****************");
User user = (User)bean;
user.setAge(18);
return bean;
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="myBeanProcessor" class="com.ppc.spring.MyBeanPostProcessor"></bean>
<bean id="user" class="com.ppc.spring.entity.User"></bean>
</beans>
entity
package com.ppc.spring.entity;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类
package com.ppc.spring;
import com.ppc.spring.controller.UserController;
import com.ppc.spring.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("springmvc.xml");
User user = classPathXmlApplicationContext.getBean("user", User.class);
System.out.println(user);
}
}
测试结果:
G:\software\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:5452,suspend=y,server=n -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\ppc\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar;G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\plugins\junit\lib\junit-rt.jar;G:\soft_install\ideaIU\IntelliJ IDEA 2019.1.1\plugins\junit\lib\junit5-rt.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-launcher\1.6.2\junit-platform-launcher-1.6.2.jar;C:\Users\ppc\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-engine\1.6.2\junit-platform-engine-1.6.2.jar;C:\Users\ppc\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\ppc\.m2\repository\org\junit\platform\junit-platform-commons\1.6.2\junit-platform-commons-1.6.2.jar;G:\software\jdk\jre\lib\charsets.jar;G:\software\jdk\jre\lib\deploy.jar;G:\software\jdk\jre\lib\ext\access-bridge-64.jar;G:\software\jdk\jre\lib\ext\cldrdata.jar;G:\software\jdk\jre\lib\ext\dnsns.jar;G:\software\jdk\jre\lib\ext\jaccess.jar;G:\software\jdk\jre\lib\ext\jfxrt.jar;G:\software\jdk\jre\lib\ext\localedata.jar;G:\software\jdk\jre\lib\ext\nashorn.jar;G:\software\jdk\jre\lib\ext\sunec.jar;G:\software\jdk\jre\lib\ext\sunjce_provider.jar;G:\software\jdk\jre\lib\ext\sunmscapi.jar;G:\software\jdk\jre\lib\ext\sunpkcs11.jar;G:\software\jdk\jre\lib\ext\zipfs.jar;G:\software\jdk\jre\lib\javaws.jar;G:\software\jdk\jre\lib\jce.jar;G:\software\jdk\jre\lib\jfr.jar;G:\software\jdk\jre\lib\jfxswt.jar;G:\software\jdk\jre\lib\jsse.jar;G:\software\jdk\jre\lib\management-agent.jar;G:\software\jdk\jre\lib\plugin.jar;G:\software\jdk\jre\lib\resources.jar;G:\software\jdk\jre\lib\rt.jar;D:\CODE\MAYUN\spring-source-analysis\target\test-classes;D:\CODE\MAYUN\spring-source-analysis\target\classes;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.3.0.RELEASE\spring-boot-starter-web-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter\2.3.0.RELEASE\spring-boot-starter-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot\2.3.0.RELEASE\spring-boot-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.0.RELEASE\spring-boot-autoconfigure-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.3.0.RELEASE\spring-boot-starter-logging-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\ppc\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\ppc\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.2\log4j-to-slf4j-2.13.2.jar;C:\Users\ppc\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.2\log4j-api-2.13.2.jar;C:\Users\ppc\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\ppc\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\ppc\.m2\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.3.0.RELEASE\spring-boot-starter-json-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.11.0\jackson-databind-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.0\jackson-annotations-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.11.0\jackson-core-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.0\jackson-datatype-jdk8-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.0\jackson-datatype-jsr310-2.11.0.jar;C:\Users\ppc\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.0\jackson-module-parameter-names-2.11.0.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.0.RELEASE\spring-boot-starter-tomcat-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.35\tomcat-embed-core-9.0.35.jar;C:\Users\ppc\.m2\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;C:\Users\ppc\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.35\tomcat-embed-websocket-9.0.35.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-web\5.2.6.RELEASE\spring-web-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-beans\5.2.6.RELEASE\spring-beans-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-webmvc\5.2.6.RELEASE\spring-webmvc-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-aop\5.2.6.RELEASE\spring-aop-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-context\5.2.6.RELEASE\spring-context-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-expression\5.2.6.RELEASE\spring-expression-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\pdfbox\1.8.16\pdfbox-1.8.16.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\fontbox\1.8.16\fontbox-1.8.16.jar;C:\Users\ppc\.m2\repository\org\apache\pdfbox\jempbox\1.8.16\jempbox-1.8.16.jar;C:\Users\ppc\.m2\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;C:\Users\ppc\.m2\repository\com\itextpdf\itextpdf\5.5.11\itextpdf-5.5.11.jar;C:\Users\ppc\.m2\repository\com\itextpdf\itext-asian\5.2.0\itext-asian-5.2.0.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.3.0.RELEASE\spring-boot-starter-test-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-test\2.3.0.RELEASE\spring-boot-test-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.3.0.RELEASE\spring-boot-test-autoconfigure-2.3.0.RELEASE.jar;C:\Users\ppc\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\ppc\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\ppc\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\ppc\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\ppc\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\ppc\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;C:\Users\ppc\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;C:\Users\ppc\.m2\repository\org\assertj\assertj-core\3.16.1\assertj-core-3.16.1.jar;C:\Users\ppc\.m2\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter\5.6.2\junit-jupiter-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.6.2\junit-jupiter-api-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.6.2\junit-jupiter-params-5.6.2.jar;C:\Users\ppc\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.6.2\junit-jupiter-engine-5.6.2.jar;C:\Users\ppc\.m2\repository\org\mockito\mockito-core\3.3.3\mockito-core-3.3.3.jar;C:\Users\ppc\.m2\repository\net\bytebuddy\byte-buddy\1.10.10\byte-buddy-1.10.10.jar;C:\Users\ppc\.m2\repository\net\bytebuddy\byte-buddy-agent\1.10.10\byte-buddy-agent-1.10.10.jar;C:\Users\ppc\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\ppc\.m2\repository\org\mockito\mockito-junit-jupiter\3.3.3\mockito-junit-jupiter-3.3.3.jar;C:\Users\ppc\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\ppc\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-core\5.2.6.RELEASE\spring-core-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-jcl\5.2.6.RELEASE\spring-jcl-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\springframework\spring-test\5.2.6.RELEASE\spring-test-5.2.6.RELEASE.jar;C:\Users\ppc\.m2\repository\org\xmlunit\xmlunit-core\2.7.0\xmlunit-core-2.7.0.jar;C:\Users\ppc\.m2\repository\org\bouncycastle\bcpkix-jdk15on\1.64\bcpkix-jdk15on-1.64.jar;C:\Users\ppc\.m2\repository\org\bouncycastle\bcprov-jdk15on\1.64\bcprov-jdk15on-1.64.jar;C:\Users\ppc\.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit5 com.ppc.spring.SpringTest
Connected to the target VM, address: '127.0.0.1:5452', transport: 'socket'
19:21:52.855 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@446293d
19:21:53.007 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [springmvc.xml]
19:21:53.037 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanProcessor'
19:21:53.065 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
***********MyBeanPostProcessor before processor****************
***********MyBeanPostProcessor after processor****************
User{name='peter', age=18}
Disconnected from the target VM, address: '127.0.0.1:5452', transport: 'socket'
Process finished with exit code 0
User对象name、age属性都有值,前置处理器、后置处理器赋值处理成功