BeanPostProcessor的主要作用在于我们可以在Spring 容器完成 Bean 的实例化、配置和其他的初始化前后添加一些自己的逻辑处理。我们就可以定义一个或者多个 BeanPostProcessor 接口的实现,然后注册到容器中。
BeanPostProcessor实现
其实这和代理模式的实现有些类似:
1、监控接口
定义所有需要被监听的行为
2、接口实现
谁来实现
3、通知类
次要业务具体实现 绑定主要和次要业务
4、监听对象
被监控的对象 需要被监控的行为 具体通知类实例对象 向JVM申请拦截
只不过是在Spring中,我们把代理对象交给Spring容器来实现了,按步骤来:
定义需要被监控的行为:
BaseService.java:
public interface BaseService {
String doSomething();
String eat();
}
谁来实现:
MyService.java
public class MyService implements BaseService{
@Override
public String doSomething() {
return "doSomething";
}
@Override
public String eat() {
return "eat food";
}
}
这里需要注意的是我们需要实现Spring的BeanPostProcessor接口:
MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前。。。。postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("初始化后。。。。postProcessAfterInitialization");
//只代理自定义的service
if (bean.getClass() == MyService.class) {
Proxy proxy = (Proxy) Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method + "方法被拦截。。。。invoke");
String result = (String) method.invoke(bean, args);
return result.toUpperCase();
}
});
return proxy;
}
return bean;
}
}
接着需要在Spring配置文件中配置相关属性:
<!-- 注册 bean:被监控的实现类 -->
<bean id="myService" class="com.lks.processor.impl.MyService"></bean>
<!-- 注册代理实现类 -->
<bean class="com.lks.processor.proxy.MyBeanPostProcessor"></bean>
测试方法:
@Test
public void testBeanPostProcessor() {
ApplicationContext factory = new ClassPathXmlApplicationContext("spring_config.xml");
BaseService service = (BaseService) factory.getBean("myService");
System.out.println(service.doSomething());
}
手写BeanPostProcessor
和Spring 一样,我们先需要定义BeanPostProcessor接口:
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
return bean;
}
default Object postProcessAfterInitializatio(Object bean, String beanName) throws Exception {
return bean;
}
}
接口实现方式基本和Spring的BeanPostProcessor接口一致,只不过这个是我们自己定义的。
接着我们需要在我们自定义的Spring容器,也就是BeanFactory中处理BeanPostProcessor:
public class BeanFactory {
//存放bean集合
private List<BeanDefined> beanDefinedList;
//存放实例化对象
private Map<String, Object> springIoc;
//beanPostProcessor属性
private BeanPostProcessor beanPostProcessor;
public BeanFactory(){
}
public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
this.beanDefinedList = beanDefinedList;
springIoc = new HashMap<>(16);
for (BeanDefined bean: beanDefinedList){
if ("singleton".equals(bean.getBeanScope())){
String classPath = bean.getClassPath();
Object instance = Class.forName(classPath).newInstance();
//判断后置对象还是普通的bean
isProcessor(instance, classPath);
springIoc.put(bean.getBeanId(), instance);
}
}
}
private void isProcessor(Object instance, String classPath) {
Class[] interfaces = instance.getClass().getInterfaces();
if (interfaces == null){
return;
}
for (Class c : interfaces){
if (c == BeanPostProcessor.class){
beanPostProcessor = (BeanPostProcessor) instance;
}
}
}
public Object getBeanPostProcessor(String beanId) throws Exception{
Object instance = null;
for (BeanDefined bean : beanDefinedList){
if (beanId.equals(beanId)){
if ("singleton".equals(bean.getBeanScope())){
instance = springIoc.get(beanId);
}else {
if (bean.getFactoryBean() != null && bean.getFactoryMethod() != null){
Object factory = springIoc.get(bean.getFactoryBean());
Method method = factory.getClass().getDeclaredMethod(bean.getFactoryMethod(), null);
method.setAccessible(true);
instance = method.invoke(factory, null);
} else {
instance = Class.forName(bean.getClassPath()).newInstance();
}
}
}
// 当前实例对象的代理监控对象
Object proxyObj = null;
//判断beanPostProcessor属性
if (beanPostProcessor != null){
proxyObj = beanPostProcessor.postProcessBeforeInitialization(instance, beanId);
proxyObj = beanPostProcessor.postProcessAfterInitialization(instance, beanId);
return proxyObj;
}else {
return instance;
}
}
return null;
}
}
新增BeanPostProcessor属性,在构造方法中判断当前的bean是不是BeanPostProcessor对象,如果是的话便初始化BeanPostProcessor,并在getBeanPostProcessor中判断返回代理对象还是普通的bean。
测试方法:
@Test
public void testMyBeanPostProcessor() throws Exception {
//注册bean
BeanDefined beanDefined = new BeanDefined();
beanDefined.setBeanId("myService");
beanDefined.setClassPath("com.lks.processor.impl.MyService");
//注册BeanPostProcessor,类似Spring配置文件配置BeanPostProcessor
BeanDefined beanObj1 = new BeanDefined();
beanObj1.setClassPath("com.lks.processor.processor.MyBeanPostProcessor");
List<BeanDefined> configuration = new ArrayList<BeanDefined>();
configuration.add(beanDefined);
configuration.add(beanObj1);
// 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
BeanFactory factory = new BeanFactory(configuration);
// 3、开发人员向BeanFactory索要实例对象
BaseService b = (BaseService) factory.getBeanPostProcessor("myService");
System.out.println("b =" + b);
System.out.println("b方法 =" + b.doSomething());
}
先注册bean,设置相关属性,然后类似Spring配置文件配置BeanPostProcessor中一样,设置BeanPostProcessor的位置。