在公司disConf分享会上,听到一个名词,BeanPostProcessor,后来在网上搜了一下,发现使用BeanPostProcessor可以解决很多看似很困难的问题。
简介
BeanPostProcessor是spring提供的一个扩展接口
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
当一个BeanPostProcessor注册到spring容器中后,对于容器在创建每一个bean时,在初始化方法调用前会调用postProcessBeforeInitialization(Object bean, String beanName)方法,在初始化方法完成后会调用postProcessorAfterInitialization(Object bean, String beanName),也就是说,spring给了我们一个机会对生成的bean进行再改造,可以修改bean的属性,将属性指向代理类或者直接生成一个bean代理返回。
下面举例为获取bean属性然后改变其引用。
先写一个注解RemoteService
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RemoteService {
}
再写一个远程代理类
public class RemoteProxy implements InvocationHandler {
Remote remote = new Remote();
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return remote.invokeRemote(method, args);
}
}
远程实现类的接口
public interface UserService {
/**
* 根据userId获取User信息
* @param userId userId
* @return userInfo
*/
Object getUser(Long userId);
}
在controller里调用使用此接口
public class UserController {
@RemoteService
UserService userService;
Object getUser(){
return userService.getUser(1L);
}
}
下面是RemoteProxyBeanPostProcessor
public class RemoteServiceBeanPostProcessor implements BeanPostProcessor {
RemoteProxy remoteProxy = new RemoteProxy();
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
if (field.isAnnotationPresent(RemoteService.class)) {
try {
field.set(bean, remoteProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return bean;
}
}
当UserController被spring实例化后,会调用RemoteServiceBeanPostProcessor里的RemoteServiceBeanPostProcessor方法,治理直接返回实例化后的bean,接着调用userController的初始化方法,最后调用RemoteServiceBeanPostProcessor里的postProcessorAfterInitialization方法,这个方法里获取到了userController里使用了RemoteService注解的field,将RemoteProxy注入到该属性中,这样在调用userService时,实际上是走的RemoteProxy代理类