拥有八块腹肌的人
没博主帅的人
项目引用了公共jar,里面定义了某些公共的service。但是本人开发中的项目需要对调用某些service的方法进行后处理
经常使用spring的人应该知道,在bean初始化的时候会调用已经注册到容器的BeanPostProcessor(不知道我也不管你)。
本人的方案是:
新建一个bean(取名为MyServiceBeanPostProcessors)实现BeanPostProcessor接口,用于拦截MyService
拦截到MyService后给MyService创建一个代理并返回(所有依赖MyService这个bean的类其实依赖的是我们新创建的代理)
代理中针对要拦截的方法做处理,其它方法则直接调用
直接上代码
MyService:jar包中的结构
public interface MyService {
String who();
}
MyServiceImpl:jar包中的实现类
@Service
public class MyServiceImpl implements MyService {
@Override
public String who() {
return "博主";
}
}
MyServiceProxy:新创建的代理
public class MyServiceProxy implements InvocationHandler {
//被代理的方法
private MyService myService;
public MyServiceProxy(MyService myService) {
this.myService = myService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("fuck")) {
//前置处理
System.out.println("我有腹肌");
//调用被代理的方法 who
Object result = method.invoke(myService, args);
//后置处理
System.out.println("我最帅");
return result;
}
return method.invoke(myService, args);
}
public MyService getProxy() {
// 给myService创建代理
return (MyService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
myService.getClass().getInterfaces(), this);
}
}
MyServiceBeanPostProcessors:(注意:@Conponent标签不能少,因为该bean也必须交给spring管理)
@Component
public class MyServiceBeanPostProcessors implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 初始化前不做任何处理
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 初始化后使用代理对象
if(bean instanceof MyService){
return new MyServiceProxy((MyService) bean).getProxy();
}
return bean;
}
}
一切感觉很完美
可是,万万没想到。完全不在意料之中,MyService这个Bean初始化的时候没有调用自定义的PostProcessor
问题出在哪呢?
难道因为博主太帅了(很有可能);
难道spring文档出问题了;
难道spring版本有问题;
掏出debug大法(感谢万能的IDEA)
警告!警告!下面会涉及一丢丢spring源码
编译成class的类一般会加上默认构造器,如下
@Service
public class MyServiceImpl implements MyService {
public MyServiceImpl() {
}
public String who() {
return "博主";
}
}
直接断点在构造方法处,看初始化此类时的调用信息。初始化Bean时会调用构造方法:
发现调用起点在如下处:应用启动时调用
org.springframework.context.support.AbstractApplicationContext.refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
// 前后方法省略
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 前后方法省略
// 调用点在这
registerBeanPostProcessors(beanFactory);
}
该方法会调用PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this),主要是注册和初始化已经被解析成BeanDefinition并且实现了BeanPostProcessor的Bean
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
下面是重点关注点,重点关注执行顺序
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有类型为BeanPostProcessor的bean
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
/**
* BeanPostProcessorChecker是一个普通的信息大于,当出现spring后置处理器还没有注册就开始
* 初始化bean的时候会打印里面设置的日志,博主的就打印了 (实现很简单,请自行查看)
*/
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 实现了PriorityOrdered的PostProcessors
List priorityOrderedPostProcessors = new ArrayList<>();
List internalPostProcessors = new ArrayList<>();
// 有序的orderedPostProcessorNames
List orderedPostProcessorNames = new ArrayList<>();
// 无序的PostProcessors
List nonOrderedPostProcessorNames = new ArrayList<>();
// 给上面的list添加值
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 实例化所有实现了 PriorityOrdered 的bean
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 排序priorityOrderedPostProcessors
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 注册priorityOrderedPostProcessors里的 PostProcessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
// 初始化与orderedPostProcessorNames里名称关联的所有bean
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// 注册orderedPostProcessors里的 PostProcessors
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 和上面流程类似
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
大致说一下上面的流程:
相信读者看了上面的流程大概也知道为什么会出现自定义到的BeanPostProcessor对有些bean无效了吧。
举个例子:如果在初始化带有优先级的BeanPostProcessor时候初始化了其它bean(对应的BeanPostProcessor依赖其他非BeanPostProcessor的bean),会导致初始化有序的,无序的BeanPostProcessor时无法对前面已经初始化的bean进行处理
我的解决方案是自定义的BeanPostProcessor实现PriorityOrdered接口(保证自定义的处理器先注册):有更好的方案请留言,欢迎弹劾:
我的方案有个问题:如果其他实现PriorityOrdered的BeanPostProcessor先初始化,并且里面实例化了其它bean,这种我还无解。------------------啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,欢迎大神赐教
@Component
public class MyServiceBeanPostProcessors implements BeanPostProcessor,PriorityOrdered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 初始化前不做任何处理
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 初始化后使用代理对象
if(bean instanceof MyService){
return new MyServiceProxy((MyService) bean).getProxy();
}
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
每天进步一点点!!欢迎各位大神参与讨论
联系邮箱:[email protected]