[toc]
由LifecycleBeanPostProcessor引起spring缓存失效说起
- springBean 加载时候各方法执行顺序
- shiro引起的种种坑
- springcache初始化过程
- spring事务初始化过程
spring4.1.6 + springmvc + spring-shiro1.4.2
springboot2.1.7 + spring-shiro1.4.2
本人没有关注是否存在这个问题, 但是事务的生效机制和cache理论上差不多
新建bean1 实现InitializingBean, DisposableBean,SmartInitializingSingleton重写相关方法,构造方法等
新建bean2 实现BeanPostProcessor,实现接口方法
新增(@Configuration)bean3 配置@bean1(指定初始化/销毁方法),@bean2
run&close springbootApplication
1. 构造方法
1.1 BeanPostProcessor#postProcessBeforeInitialization
2. @PostConstruct修饰的方法
3. InitializingBean#afterPropertiesSet
4. 指定的init函数
4.1 BeanPostProcessor#postProcessAfterInitialization
5. SmartInitializingSingleton#afterSingletonsInstantiated
6. DisposableBean#destroy
7 指定的销毁方法
AuthorizingRealm extends AuthenticatingRealm
implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware
public class LifecycleBeanPostProcessor implements DestructionAwareBeanPostProcessor, PriorityOrdered {
//把本后置处理器在PriorityOrdered级别中优先级置为最低
public LifecycleBeanPostProcessor() {
this(LOWEST_PRECEDENCE);
}
//前置处理逻辑
public Object postProcessBeforeInitialization(Object object, String name) throws BeansException {
if (object instanceof Initializable) {
((Initializable) object).init();
}
return object;
}
}
结论:LifecycleBeanPostProcessor会导致realm中注入的service提前初始化。
另外:LifecycleBeanPostProcessor实现了PriorityOrdered,并把order置为最低,表示在所有后置处理器中优先级很高(而且高于同级别的实现PriorityOrdered的处理器)
再次回顾下bean初始化和销毁的执行顺序
BeanPostProcessor本身也是一个Bean, 那么它的初始化时机是什么呢?
AbstractApplicationContext#refresh()——>registerBeanPostProcessors(beanFactory)方法会注册BeanPostProcessors:
源码略,摘录部分注释如下:
注册BeanPostProcessorChecker,它在以下情况下记录信息消息:
bean是在BeanPostProcessor实例化期间创建的,即
bean不适合由所有beanPostProcessor处理。
检查可在当前Bean上起作用的BeanPostProcessor个数与总的BeanPostProcessor个数,
如果起作用的个数少于总数打印:
xxx is not eligible for getting processed by all BeanPostProcessors
(for example: not eligible for //auto-proxying)
根据是否实现 PriorityOrdered,Ordered, and the rest来区分BeanPostProcessors
1,注册实现 PriorityOrdered BeanPostProcessors
PriorityOrdered类型的BeanPostProcessor会预初始化
2,注册实现 Ordered BeanPostProcessors
3 注册所有无序(没有实现Ordered/ PriorityOrdered) BeanPostProcessors.
4, 注册所有内部(MergedBeanDefinitionPostProcessor) BeanPostProcessors.
结论:BeanPostProcessor注册顺序如下:
实现了PriorityOrdered的BeanPostProcessor先于其他BeanPostProcessor,并会影响到其他BeanPostProcessor的autowiring behavior(参见PriorityOrdered接口上的注释)
public interface PriorityOrdered extends Ordered {
}
spring标签的解析器全都实现了NamespaceHandlerSupport
(来自spring-beans包)
其中 CacheNamespaceHandler就是用于解析<cache:annotation-driven />标签
public class CacheNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new
AnnotationDrivenCacheBeanDefinitionParser());
registerBeanDefinitionParser("advice", new CacheAdviceParser());
}
}
根据源码,可以看出将下列重要类注册到容器中:
InfrastructureAdvisorAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口(此接口集成了BeanPostProcessor接口)
回顾下前文的类生命周期执行顺序
InfrastructureAdvisorAutoProxyCreator部分源码摘录:
//执行顺序对应上文的 4.1 BeanPostProcessor#postProcessAfterInitialization, 在初始化其他bean的时候织入此逻辑
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// 1 获取当前类的所有切面拦截类
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//2 如果拦截类不为空,则需要创建当前类的代理类
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//3.创建代理类
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
BeanFactoryCacheOperationSourceAdvisor
1)解析<cache:annotation-driven />,将InfrastructureAdvisorAutoProxyCreator注入到Spring容器中,该类的作用是在Spring创建bean实例的时候,会执行其postProcessAfterInitialization()方法,生成bean实例的代理类
2)解析<cache:annotation-driven />,将BeanFactoryCacheOperationSourceAdvisor类注入到Spring容器中,该类的主要作用是作为一个Advisor添加到上述代理类中
3)BeanFactoryCacheOperationSourceAdvisor类拥有对CacheInterceptor的依赖,CacheInterceptor作为一个方法拦截器,负责对缓存方法的拦截,
4)当前类方法调用被拦截到CacheInterceptor后,CacheInterceptor会调用我们在配置文件中配置的CacheManager实现(也就是本例中的SimpleCacheManager),来真正实现缓存功能
从@EnableCaching开始,
引入了@Import({CachingConfigurationSelector.class})
这个类添加了AutoProxyRegistrar.java,ProxyCachingConfiguration.java两个类
过程略,参见文末的“本文参考”。
了解了springcache的原理之后,事务的原理就呼之欲出了,二者基本都是一个理念都是一致的。
public class TxNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new
JtaTransactionManagerBeanDefinitionParser());
}
}
被BeanPostProcessor 提前初始化的bean还会进入其他BeanPostProcessor 吗?
主要的原因是对很多原理性的东西不熟悉, 我会在后续的时间里,慢慢的一点点的补充吧,