[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#postProcessBeforeInitialization2. @PostConstruct修饰的方法3. InitializingBean#afterPropertiesSet4. 指定的init函数4.1 BeanPostProcessor#postProcessAfterInitialization5. SmartInitializingSingleton#afterSingletonsInstantiated6. DisposableBean#destroy7 指定的销毁方法
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来区分BeanPostProcessors1,注册实现 PriorityOrdered BeanPostProcessorsPriorityOrdered类型的BeanPostProcessor会预初始化2,注册实现 Ordered BeanPostProcessors3 注册所有无序(没有实现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 {@Overridepublic void init() {registerBeanDefinitionParser("annotation-driven", newAnnotationDrivenCacheBeanDefinitionParser());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;}
BeanFactoryCacheOperationSourceAdvisor1)解析<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 {@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", newJtaTransactionManagerBeanDefinitionParser());}}
被BeanPostProcessor 提前初始化的bean还会进入其他BeanPostProcessor 吗?
主要的原因是对很多原理性的东西不熟悉, 我会在后续的时间里,慢慢的一点点的补充吧,