Spring AOP
核心组件概念以及作用
JoinPoint: 连接点,在Spring AOP中指代调用方法,核心实现有MethodInvocation、ReflectiveMethodInvocationPointcut: 切入点,在Spring AOP中指代对具体的连接点的过滤,比如Spring中的ClassFilter/MethodMatcher等Advice: 通知,就是具体的增强代码,有前置后置,环绕等.. , 核心实现为MethodInterceptorAspect:是包含上面组件的类(Spring AOP)中。Advisor: 是Advice的容器,其中可以获取通知类,一般实现有两种PointcutAdvisor/IntroductionAdvisor,前者提供PointCut过滤,后者提供ClassFilter过滤AopProxy: 表示Aop代理对象,提供getProxy()来获取代理对象,有动态代理和Cglib字节码提升两种实现方式AopProxyFactory: Aop代理工厂,通过传入AdvisedSupport配置信息来创建AopProxy对象,默认实现为DefaultAopProxyFactoryAdvisedSupport: 扩展了ProxyConfig类,提供了目标源对象TargetSource的管理和所有Advisor通知类,以及进行Advice到MethodInterceptor适配工作的AdvisorChainFactoryAdvisorAdaptor/AdvisorAdaptorRegistry,AdvisorChainFactory通过AdvisorAdaptoyRegistry注册的AdvisorAdaptor将Advisor适配成MethodInterceptorAbstractAutoProxyCreator: 自动代理类,实现了SmartInstantiationAwareBeanPostProcessor,在postProcessBeforeInstantiation()/postProcessAfterInitialization()进行代理拦截,并且通过依赖查找来打通AOP和IOC
自动代理实现原理
通常我们在代码中使用AOP的方式都是整合了IOC的自动代理模式,即
AutoProxyCreator这个抽象实现,重点聚焦于AnnotationAwareAspectJAutoProxyCreator,这也是@EnableAspectJAutoProxy的原理
AnnotationAwareAspectJAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor的实现类 , 所以观察可知,在Bean的实例化以及初始化前后会有一定增强。目光聚焦到postProcessAfterInitialization()
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//1. 查看是否命中缓存
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//2. 若之前的缓存和现在的bean不同,则进行增强
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//3. 增强方法
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
- 继续来跟进
wrapIfNecessary(bean,beanName,cacheKey)
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//1. 命中缓存直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//2. 相关切面相关类也直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//3. 判断是否是切面相关类型 shouldSkip -> 会获取获取切面并解析成Advisor
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取Advisor/Advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
/*使用代理工厂获取代理对象*/
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;
}
2.1 其中重要的两个步骤
- 获取所有的
Advisor
//核心代理,获取所有的Advisor/切面 Bean
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//AbstractAdvisorAutoProxyCreator
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
/*查询所有有效的Advisor*/
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
//查询有效的Advisor类
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
/*1. 在IOC中查找Advisor相关Bean以及切面Bean*/
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/*2. 过滤获取需要拦截beanClass的Advisor*/
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
/*3. AspectJ扩展候选的Advisor*/
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
/*4. 进行Order排序*/
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
- 创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
/*1. 在BeanDefinition中存储Target Class引用*/
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); /*AbstractAutoProxyCreator本来也是ProxyConfig的子类*/
//判断是否需要使用CGLIB
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//从是否有接口判断
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 获取合并后的Advisor (手动添加的InterceptorNames + Advisor + AspectJ注解方法(AspectJ 注解环境下))
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//使用代理工厂创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
-
当创建代理对象后,调用代理对象的方法会回调到
JdkDynamicAopProxy#invoke()方法,原因是创建代理对象的时候将相关的AopProxy实现当做InvocationHandler/MethodInterceptor3.1
基于接口的代理:JdkDynamicAopProxy#invoke()3.2
基于类的代理:CglibAopProxy$DynamicAdvisedInterceptor#intercept()方法
//用Jdk动态代理作为示例,下面截取了invoke()的核心步骤
// JdkDynamicAopProxy#invoke()
/*若开启了exposeProxy = true则将代理对象设置到AopContext的ThreadLocal中*/
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
/*委派给AdvisorChainFactory将所有的Advisor适配成MethodInterceptor*/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
/*若没有通知拦截对象,则直接进行目标连接点反射调用*/
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
/*封装成ReflectiveMethodInvocation进行代理调用*/
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//执行JoinPoint的方法
retVal = invocation.proceed();
}
ReflectiveMethodInvocation#proceed()
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
/*1. 若当前责任链索引游标等于所有通知类size-1则直接调用目标方法 (到达了最后一个MethodInterceptor拦截)*/
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
/*2. 获取最后一个MethodInterceptor*/
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
/*3. 处理InterceptorAndDynamicMethodMatcher类型的MethodInterceptor,先进行MethodMatcher匹配 (AspectJ #DeclareParents)*/
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
/*4. 一般都会到这一步,执行当前责任链索引对应的MethodInterceptor#invoke方法*/
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
几种常见MethodInterceptor的实现
- 前置
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
//在目标方法调用执行,执行before
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
- 后置
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
- 环绕
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
public AspectJAroundAdvice(
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
//调用Aspect @Around标记的方法,然后通过ProceedJoinPoint来回调目标方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
Spring AOP应用整合场景之SpringTX
核心观察Spring如何使用AOP来整合事务,重点观察@EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//导入了一个Configuration Class
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//是否使用基于类的代理
boolean proxyTargetClass() default false;
//代理的模式
AdviceMode mode() default AdviceMode.PROXY;
//代理类的序号
int order() default Ordered.LOWEST_PRECEDENCE;
}
查看
TransactionManagenetConfiurationSelector,是一个ImportSelector的实现,该类实现都是通过ConfigurationClassPostProcessor来回调从而向IOC添加单实例Bean
public class TransactionManagementConfigurationSelector extends
//1. AdviceModeImportSelector是类似模板方法,作用是读取@EnableXX注解上的注解元信息并将AdviceMode传递给子类
AdviceModeImportSelector<EnableTransactionManagement> {
//2. 根据用户设置的通知模式(Proxy/AspectJ)来进行注入相关的Bean
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
AutoProxyRegistrar
自动代理类的注册类 , 实现了
ImportBeanDefinitionRegistrar,通过registerBeanDefinitions()注入Bean
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
//1. 获取导入类的注解类型 (@EnableXXX)
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
//2. 获取属性元信息
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
//3. 获取对应的属性值
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
//4. 使用AopConfigUtils注册AutoProxyCreater自动代理类到IOC中
if (mode == AdviceMode.PROXY) {
/*1. 注册InfrastructureAdvisorAutoProxyCreator自动代理类到IOC中*/
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
/*2. 设置CGLIB代理*/
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
ProxyTransactionManagementConfiguration
这个类是事务功能的相关配置类 ,其中主要添加了如下组件到IOC中
-
TransactionAttributeSource: 读取方法或者类上的@Transactional注解的类 -
TransactionInterceptor: 拦截事务的主要通知类 -
BeanFactoryTransactionAttributeSourceAdvisor: 事务的相关Advisor类,其中说明只针对@Transactional注解的方法/类进行拦截(Pointcut机制) -
TransactionalEventListenerFactory: 事务的监听器机制@TransactionalEventListener,可以方便我们在事务的提交前后执行监听业务的执行 -
TransactionManagementConfigurer: 事务管理扩展配置类,可以通过添加该类到IOC中来对TransactionManager进行自定义
BeanFactoryTransactionAttributeSourceAdvisor源码
Advisor主要有两部分组成,一个是Advice通知类 ,这里为
TransactionInterceptor,一个是过滤,这里是TransactionAttributeSourcePointcut,
TransactionAttributeSourcePointcut: 通过判断是否有@Transcational元信息
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
//通过TransactionAttributesSource判断当前方法/类上是否有@Transactional注解
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
}
TransactionInterceptor:aop通知拦截
//TransactionInterceptor#invoke()
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
//1. 获取目标Class
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
//2. kotlin调用
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
if (KotlinDetector.isSuspendingFunction(invocation.getMethod())) {
InvocationCallback callback = new CoroutinesInvocationCallback() {
@Override
public Object proceedWithInvocation() {
return CoroutinesUtils.invokeSuspendingFunction(invocation.getMethod(), invocation.getThis(), invocation.getArguments());
}
@Override
public Object getContinuation() {
return invocation.getArguments()[invocation.getArguments().length - 1];
}
};
return invokeWithinTransaction(invocation.getMethod(), targetClass, callback);
}
//3. 主要会进入这里,传入目标方法的调用Supplier
/*调用父类执行事务*/
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
invokeWithinTransaction()
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource(); /*1. normally that is AnnotationTransactionAttributeSource*/
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); /*2. 尝试获取TransactionAttributes*/
final TransactionManager tm = determineTransactionManager(txAttr); /*3. 查找对应的事务管理器*/
/*4. 省略Reactive Programing 事务支持*/
//...
/*5. 转化成PlatformTransactionManager*/
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
/*6. 获取连接点方法描述*/
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
/*7. 一般会进入这个分支(除了WebSphere和Test模块的Mock)*/
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
/*7.1 根据不同的传播特性来跳过创建事务,创建新事务,嵌套事务等..并返回事务信息*/
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
/*7.2 执行目标方法*/
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
/*Commit事务*/
commitTransactionAfterReturning(txInfo);
return retVal;
}
总结
- 通过
@EnableTransactionManagement导入相关的Advisor拦截和TransactionAttributeSource属性元数据解析器
SpringAOP整合场景之Spring Caching
Spring Caching和事务的整合基本类似,下面直接总结核心组件和步骤
AutoProxyRegistrar: 导入自动代理类CachingConfigurer:定制配置类ProxyCachingConfiguration: 核心配置类BeanFactoryCacheOperationSourceAdvisor和CacheInterceptor: 代理拦截类CacheOperationSource: 属性解析类
核心拦截步骤
//CacheAspectSupport#execute()
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
//特殊处理,@Cachable(sync=true),这种方式只会处理这一个注解
// Special handling of synchronized invocation
if (contexts.isSynchronized()) {
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
Cache cache = context.getCaches().iterator().next();
try {
return wrapCacheValue(method, handleSynchronizedGet(invoker, key, cache));
}
catch (Cache.ValueRetrievalException ex) {
// Directly propagate ThrowableWrapper from the invoker,
// or potentially also an IllegalArgumentException etc.
ReflectionUtils.rethrowRuntimeException(ex.getCause());
}
}
else {
// No caching required, only call the underlying method
return invokeOperation(invoker);
}
}
// Process any early evictions
/*1. CacheEvict执行(通过@CacheEvict#beforeInvocation=true)来控制在方法调用之前执行清除缓存,这是可以无视目标方法调用是否抛出异常都清除缓存,默认false*/
processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
CacheOperationExpressionEvaluator.NO_RESULT);
// Check if we have a cached item matching the conditions
/*2. 获取缓存*/
Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));
// Collect puts from any @Cacheable miss, if no cached item is found
List<CachePutRequest> cachePutRequests = new ArrayList<>();
/*3. 缓存中没有对应的key*/
if (cacheHit == null) {
/*4. 收集缓存更新*/
collectPutRequests(contexts.get(CacheableOperation.class),
CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
}
Object cacheValue;
Object returnValue;
/*5. 若有缓存,且没有缓存更新,则返回缓存*/
if (cacheHit != null && !hasCachePut(contexts)) {
// If there are no put requests, just use the cache hit
cacheValue = cacheHit.get();
returnValue = wrapCacheValue(method, cacheValue);
}
/*6. 否则则执行目标方法*/
else {
// Invoke the method if we don't have a cache hit
returnValue = invokeOperation(invoker);
cacheValue = unwrapReturnValue(returnValue);
}
/*7. 再次收集缓存更新操作*/
// Collect any explicit @CachePuts
collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
// Process any collected put requests, either from @CachePut or a @Cacheable miss
for (CachePutRequest cachePutRequest : cachePutRequests) {
/*8. 执行put*/
cachePutRequest.apply(cacheValue);
}
/*9. 最后执行清除*/
// Process any late evictions
processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
return returnValue;
}
- 若开启了@Cacheable(sync=true)则只单独处理这一个注解
- 若@CacheEvict(beforeInvocation=true)则先清除缓存
- 尝试从缓存中获取缓存
- 若有缓存且没有@Cacheput操作,则直接返回
- 否则则调用目标方法,将结果存入缓存中
- 清除缓存(如果有@CacheEvict(beforeInvocation=false)的话)