Spring5源码之BeanPostProcessor

这篇文章主要介绍了Spring5源码之BeanPostProcessor的接口,这是Spring中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring,需要的朋友可以参考一下。

1、BeanPostProcessor接口

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

/**
 * Factory hook that allows for custom modification of new bean instances,
 * e.g. checking for marker interfaces or wrapping them with proxies.
 *
 * <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
 * bean definitions and apply them to any beans subsequently created.
 * Plain bean factories allow for programmatic registration of post-processors,
 * applying to all beans created through this factory.
 *
 * <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}.
 *
 * @author Juergen Hoeller
 * @since 10.10.2003
 * @see InstantiationAwareBeanPostProcessor
 * @see DestructionAwareBeanPostProcessor
 * @see ConfigurableBeanFactory#addBeanPostProcessor
 * @see BeanFactoryPostProcessor
 */
public interface BeanPostProcessor {

源码定义:工厂挂钩,允许用户自定义修改新的bean实例,例如:检查标记接口或用代理包装它们。

2、实现BeanPostProcessor接口的案例

  • 普通的bean:Dog
package com.test.bean;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
public class Dog {
	private String name;
	private Integer age;

	public void print() {
		log.info("dog name:{} age:{}", name, age);
	}

}
  • 实现BeanPostProcessor接口的bean:DogBeanPostProcessor
package com.test.processor;

import com.test.bean.Dog;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @Description: 自定义DogBeanPostProcessor
 * @Author: Janson
 * @Date: 2020/4/6 15:40
 **/
public class DogBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return dealWithDog(bean, true);
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return dealWithDog(bean, false);
	}

	private Object dealWithDog(Object bean, boolean isBefore) {
		if (bean instanceof Dog) {
			Dog dog = (Dog) bean;
			if (!isBefore) {
				dog.setName("SIBERIAN HUSKY");
				dog.setAge(2);
			}
			dog.print();
			return bean;
		}
		return bean;
	}

}
  • resources目录下配置的xml文件:bean.xml
<?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="dog" class="com.test.bean.Dog">
		<property name="name" value="Hello Dog"></property>
		<property name="age" value="1"></property>
	</bean>

	<bean id="dogBeanPostProcessor" class="com.test.processor.DogBeanPostProcessor"></bean>

</beans>
  • 测试类BeanPostProcessorTest
package com.test;

import com.test.bean.Dog;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description: BeanPostProcessor测试类
 * @Author: Janson
 * @Date: 2020/4/6 15:40
 **/
public class BeanPostProcessorTest {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
		Dog dog = (Dog) applicationContext.getBean("dog");
	}
}
  • 程序执行可以看到如下的结果:
16:58:52.886 [main] INFO com.test.bean.Dog - dog name:Hello Dog age:1
16:58:52.887 [main] INFO com.test.bean.Dog - dog name:SIBERIAN HUSKY age:2
  • 总结:从程序的执行结果可以看到两点:
    1、我们在前处理器postProcessBeforeInitialization方法中输出我们初始化定义的Dog属性为name:Hello Dog age:1。
    2、我们通过自定义的处理器DogBeanPostProcessor在postProcessAfterInitialization方法对Dog类中的原始属性name和age进行了修改,输出我们修改的结果为dog name:SIBERIAN HUSKY age:2。

3、源码AbstractAutowireCapableBeanFactory的实现

  • 初始化bean的方法initializeBean
/**
* 初始化bean的方法
**/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	// 初始化bean之前
	if (mbd == null || !mbd.isSynthetic()) {
		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);
	}
	// 初始化bean之后
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}
  • 初始化bean的方法调用前处理器applyBeanPostProcessorsBeforeInitialization
/**
 * 初始化bean的方法调用前
 */
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		// 调用自定义的postProcessBeforeInitialization方法
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}
  • 初始化bean的方法调用后处理器applyBeanPostProcessorsAfterInitialization
/**
 * 初始化bean方法调用后
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		// 调用自定义的postProcessAfterInitialization方法
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

如果您觉得有帮助,欢迎点赞哦 ~ ~ 多谢~ ~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值