
Interface Introduction
There is an interface in spring named BeanPostProcessor. It has 2 functions:
public interface BeanPostProcessor
{
public abstract Object postProcessBeforeInitialization(Object obj, String s)
throws BeansException;
public abstract Object postProcessAfterInitialization(Object obj, String s)
throws BeansException;
}
We can know it from the name of its function:
- postProcessBeforeInitialization: Operate before init
- postProcessAfterInitialization: Operate after init
Source Code
We find its source from the AbstractAutowireCapableBeanFactory class:
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()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
And the source code of applyBeanPostProcessorsBeforeInitialization and applyBeanPostProcessorsAfterInitialization is:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
From the code we know around invokeInitMethods, spring will invoke BeanPostProcessor and do its functions. In invokeInitMethods, there are 2 important points:
- Judge whether extends InitializingBean, if so then invoke afterPropertiesSet().
- Judge whether set the init-method, if so then do the function which is setted.
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
Example
1. Define interface and implementation
DemoService interface
public interface DemoService {
public void sayHello();
}
DemoServiceImpl
public class DemoServiceImpl implements DemoService,NameInit {
String name;
@Override
public void sayHello() {
System.out.println("hello "+name);
}
@Override
public void setName(String name) {
this.name=name;
}
}
2. Define bean
<bean id="demoService" class="com.zjl.beanpostprocessor.DemoServiceImpl">
</bean>
3. Define inject interface
public interface NameInit {
public void setName(String name);
}
4. Define a BeanPostProcessor instence and if it extends NameInit then inject name.
public class NameBeanPostProcessor implements BeanPostProcessor {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof NameInit){
((NameInit)bean).setName(name);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
5. Define bean and inject name value
<bean id="nameBeanPostProcessor" class="com.zjl.beanpostprocessor.NameBeanPostProcessor">
<property name="name" value="kincolle"></property>
</bean>
6. define another BeanPostProcessor and print log
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("running:"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("running done:"+beanName);
return bean;
}
}
7. Define bean
<bean id="logBeanPostProcessor" class="com.zjl.beanpostprocessor.LogBeanPostProcessor">
</bean>
8. Test
public class BeanPostProcessorTest {
public static void main(String[] args) {
ApplicationContext context=new FileSystemXmlApplicationContext("beanpostprocessor.xml");
DemoService demoService=(DemoService) context.getBean("demoService");
demoService.sayHello();
}
}
9. Result
running:demoService
running done:demoService
hello kincolle




近期评论