public class Handler { public int handle() { return 1; } }创建切面
@Aspect @Component @Slf4j public class LogAspect { @Pointcut("execution(public int com.example.demo.handler.Handler.*(..))") public void pointcut() {}; @Before("pointcut()") public void logBefore() { log.info("log before"); } @After("pointcut()") public void logAfter() { log.info("log after"); } }增加配置
@Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) public class AspectConfiguration { @Bean public Handler handler() { return new Handler(); } @Bean public LogAspect logAspect() { return new LogAspect(); } }运行
此时后台会打印
log before
log after
概念理解 Joinpoint程序中的执行点,常见的有如下几种
- 方法调用
- 方法调用执行
- 构造方法调用
- 构造方法调用执行
- 字段设置
- 字段获取
- 异常处理执行
- 类初始化
调用和调用执行的区别
在spring aop中,仅支持方法调用执行类型的Joinpoint
用来选择一些Joinpoint的表达式
下面是Java中对该概念的实现
public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); Pointcut TRUE = TruePointcut.INSTANCE; }
ClassFilter用来过滤类,MethodMatcher用来过滤方法
public interface ClassFilter { boolean matches(Class> clazz); ClassFilter TRUE = TrueClassFilter.INSTANCE; }
public interface MethodMatcher { // 只对方法的名称进行过滤 boolean matches(Method method, Class> targetClass); // 当返回true时,代表是动态的,此时会顺序执行两个参数版本的match和三个参数版本的match,只有都返回true才会进行增强 // 当返回false时,代表是静态的,此时只会执行两个参数版本的match boolean isRuntime(); // 不仅对方法的名称进行顾虑,而且会对方法的参数进行过滤 boolean matches(Method method, Class> targetClass, Object... args); MethodMatcher TRUE = TrueMethodMatcher.INSTANCE; }
根据isRuntime的返回值,MethodMatcher又分为静态的StatisMethodMatcher和动态的DynamicMethodMatcher
下面是常见的几种PointCut
- NameMatchMethodPointcut 通过方法的名称来进行匹配
- JdkRegexpMethodPointcut 通过正则表达是来进行匹配
- AnnotationMatchingPointcut 通过是否使用指定的注解来进行匹配
- ComposablePointcut 组合多个Pointcut
在Joinpoint执行的具体增强逻辑,一共有如下几种类型
- Before Advice
在Joinpoint之前执行 - After Advice
在Joinpoint之后执行 - After returning Advice
在Joinpoint正常返回之后执行 - After throwing Advice
在Joinpoint抛出异常时执行 - After Advice
在Joinpoint执行完毕之后执行,不管是否正常执行 - Around Advice
在Joinpoint执行之前和之后执行 - Introduction
不同于其他Advice,为指定对象添加新的行为
IntroductionInterceptor用来实现Introduction
MethodInterceptor相当于AroundAdvice
用来组合PointCut和Advice,即指定在哪些执行点执行哪些增强逻辑
用来实现AOP中的Aspect,但是两者还是有些地方不同
Advisor中只能有一个Pointcut和一个Advice,而Aspect可以有多个Pointcut和多个Advice
Advisor主要分为两类:PointcutAdvisor和IntroductionAdvisor
@import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false; }
该注解的主要作用就是通过@import注解引入AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrarclass AspectJAutoProxyRegistrar implements importBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) { // 注册一个AspectJAnnotationAutoProxyCreator AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); // 获取注解信息 AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassmetadata, EnableAspectJAutoProxy.class); // 将注解上的信息设置到之前注册的bean上 if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }registerAspectJAnnotationAutoProxyCreatorIfNecessary
向容器中注册一个AnnotationAwareAspectJAutoProxyCreator
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); // 判断容器中是否有名称为org.springframework.aop.config.internalAutoProxyCreator的bean if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { // 当前容器中已经存在名称为org.springframework.aop.config.internalAutoProxyCreator的bean BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); // 已有bean的类型和当前需要注册的类不同 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { // 确定两个类的优先级 // InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); // 将bean的类型设置为优先级最高的类型 if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // 不存在名为org.springframework.aop.config.internalAutoProxyCreator的bean // 创建beanDefinition并注册 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }forceAutoProxyCreatorToUseClassProxying
该方法修改了beanDefinition,将proxyTargetClass设置为true
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); } }forceAutoProxyCreatorToExposeProxy
该方法修改了beanDefinition,将exposeProxy设置为true
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); } }AnnotationAwareAspectJAutoProxyCreator
看下类继承结构
首先看下AbstractAutoProxyCreator,其实现了SmartInstantiationAwareBeanPostProcessor
这里主要看下postProcessBeforeInstantiation
在每个bean实例化之前进行拦截,判断是否有处理当前bean的TargetSource,如果有会创建该TargetSource,将TargetSource作为被代理的对象,然后执行增强,并返回
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { // 获取缓存key Object cacheKey = getCacheKey(beanClass, beanName); // 如果beanName为null或者不在targetSourcedBean中 if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { // advisedBeans存放已经经过切面处理或者判断为不需要进行切面处理的bean if (this.advisedBeans.containsKey(cacheKey)) { return null; } // 判断不需要进行增强,以下两种情况不需要进行增强 // isInfrastructureClass用来判断当前类是否是aop相关的基础类,比如Advice、Pointcut、Advisor、AopInfrastructureBean // shouldSkip会被子类重写 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { // 标志为不需要进行增强 this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. if (beanName != null) { // 判断是否需要对当前bean创建targetSource TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { // 判断为需要创建targetSource // 将当前bean标记为经过targetSource的处理 this.targetSourcedBeans.add(beanName); // 获取当前适用于当前bean的advice和advisor Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建代理对象 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
获取缓存key,针对bean的类型,生成真实的beanName
protected Object getCacheKey(Class> beanClass, String beanName) { // 判断是否是FactoryBean,如果是的话会在beanName之前加上& if (StringUtils.hasLength(beanName)) { return (FactoryBean.class.isAssignableFrom(beanClass) ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName); } else { return beanClass; } }postProcessAfterInitialization
在所有bean初始化完成之后进行拦截,判断当前bean是否需要增强
这里不会对在postProcessBeforeInstantiation中创建过TargetSource并进行过增强的bean再进行一次处理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 该bean已经在创建targetSource时进行过代理 *** 作,直接返回 if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } // 当前bean不需要进行增强 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 当前bean是aop基础类或者认为需要跳过 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 获取适用于当前bean的增强逻辑 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { // 有增强逻辑 // 将当前bean标志为已经被增强 this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理 // 可以看到这里也会为初始化后的bean创建一个SingletonTargetSource 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; }createProxy
protected Object createProxy( Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { // 将beanDefinition中的originalTargetClass属性设置为beanClass AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } // 读取当前有关aop的配置,设置到ProxyFactory中 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); // 当前proxyTargetClass配置设置为false,代表不启用cglib代理 if (!proxyFactory.isProxyTargetClass()) { // 判断当前bean需要使用proxyTargetClass // 当beanDefinition的preserveTargetClass属性设置为true时会判断为需要使用cglib代理 if (shouldProxyTargetClass(beanClass, beanName)) { // 将proxyFactory的proxyTargetClass设置为true proxyFactory.setProxyTargetClass(true); } else { // 判断是否有有效接口,如果没有,那么切换到使用cglib来生成代理 evaluateProxyInterfaces(beanClass, proxyFactory); } } // 将interceptor转换成advisor,设置到ProxyFactory中 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 创建代理对象,具体过程可以看到另外一篇文章https://editor.csdn.net/md/?articleId=98391083 return proxyFactory.getProxy(getProxyClassLoader()); }evaluateProxyInterfaces
protected void evaluateProxyInterfaces(Class> beanClass, ProxyFactory proxyFactory) { // 获取当前bean实现的所有接口,包括父类实现的接口 Class>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; for (Class> ifc : targetInterfaces) { // 判断是否是有效接口,需要通过以下三个规则校验 // 不是spring中的回调接口,比如InitializingBean ,DisposableBean等 // 不是内部接口,比如GroovyObject, 以.cglib.proxy.Factory结尾的类等 // 接口中有方法 if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) { hasReasonableProxyInterface = true; break; } } // 具有有效接口,将接口添加到proxyFactory中 if (hasReasonableProxyInterface) { // Must allow for introductions; can't just set interfaces to the target's interfaces only. for (Class> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } } else { // 没有有效接口,设置为使用cglib代理 proxyFactory.setProxyTargetClass(true); } }buildAdvisors
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { // Handle prototypes correctly... // 默认情况下是空 Advisor[] commonInterceptors = resolveInterceptorNames(); // 合并commonInterceptors和添加的interceptor ListAbstractAdvisorAutoProxyCreator getAdvicesAndAdvisorsForBean
下面看下如何找到当前bean需要使用的Advisor
protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName, TargetSource targetSource) { List advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
protected List findEligibleAdvisors(Class> beanClass, String beanName) { // 从容器中获取Advisor类型的bean,AnnotationAwareAspectJAutoProxyCreator会重写这部分逻辑 List candidateAdvisors = findCandidateAdvisors(); // 选择需要应用到当前bean的增强 List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 钩子方法,子类可以重写这个方法,来增强额外的advisor extendAdvisors(eligibleAdvisors); // 对Advisor进行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }AnnotationAwareAspectJAutoProxyCreator
通过上面的源码我们了解到,spring会从容器中获取Advisor类型的bean,然后将能够应用到当前bean的Advisor挑选出来,设置到ProxyFactory,ProxyFactory在生成代理对象的时候,会使用这些Advisor
那么我们通过@Aspect注解声明的Advisor又是如何注入到容器中的呢,这些Advisor并没有实现Advisor接口
AnnotationAwareAspectJAutoProxyCreator会完成这些工作
AbstractAdvisorAutoProxyCreator实现了BeanFactoryAware
public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalArgumentException( "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); } initBeanFactory((ConfigurableListableBeanFactory) beanFactory); }
AnnotationAwareAspectJAutoProxyCreator重写了initBeanFactory
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { super.initBeanFactory(beanFactory); if (this.aspectJAdvisorFactory == null) { this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); } this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); }findCandidateAdvisors
接着看下AnnotationAwareAspectJAutoProxyCreator是如何重写findCandidateAdvisors的
protected List findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 从容器中获取Advisor类型的bean List advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 解析使用了@Aspect注解的类 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
先看下super.findCandidateAdvisors,会调用AbstractAdvisorAutoProxyCreator的findCandidateAdvisors
// AbstractAdvisorAutoProxyCreator protected List findCandidateAdvisors() { return this.advisorRetrievalHelper.findAdvisorBeans(); }
// BeanFactoryAdvisorRetrievalHelper public List findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! // 从容器中获取Advisor类型的bean advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } if (advisorNames.length == 0) { return new ArrayList(); } List advisors = new ArrayList(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
上述方法的主要作用就是从容器中取出Advisor类型的bean
接着看下AspectJAdvisorsBuilder的buildAspectJAdvisors
public List buildAspectJAdvisors() { ListaspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List advisors = new linkedList(); aspectNames = new linkedList (); // 从容器中取出所有bean的名称 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. // 获取bean的类型 Class> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 判断是否使用了@Aspect注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); Aspectmetadata amd = new Aspectmetadata(beanType, beanName); // 根据aspect不同的实例化模式,实例化aspect if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { metadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } metadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List advisors = new linkedList(); for (String aspectName : aspectNames) { List cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { metadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)