本文主要介绍Spring的 aop:aspectj-autoproxy/ 标签,了解spring是如何实现扫描注解进行aop的,主要实现是在 AspectJAutoProxyBeanDefinitionParser的parser方法中,另外这里
还需要了解一下NamespaceHandler, NamespaceHandlerSupport 和 BeanDefinitionParser 的关系,如果不清楚的可以看一下 Spring源码之ApplicationContext 中的解释。
在讲述aop源码之前,需要先了解一下 Jdk 动态代理和 CGLIB 代理的区别和使用。
描述
Jdk动态代理需要目标类至少实现一个接口,在运行时期生成代理类。
CGLIB代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但CGLIB会继承目标对象,需要重写方法,所以目标对象不能为 final 类。
示例是基于注解形式,AspetJTest类为注解类。
package lantao.aop; import java.lang.annotation.*; /** * @Auther: lantao * @Date: 2019-05-09 14:01 * @Company: 随行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AspetJTest { } 复制代码
Config为Aop的配置类,Pointcut(切点)配置为AspetJTest注解,则所有使用@AspetJTest注解的方法都会被代理。
package lantao.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * @Auther: lantao * @Date: 2019-05-09 14:03 * @Company: 随行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */ @Aspect @Component public class Config { @Pointcut("@annotation(AspetJTest)") public void serviceAspect() { } @Around("serviceAspect()") public Object Around(ProceedingJoinPoint point) throws Throwable { System.out.println("进入Around方法"); Object proceed = point.proceed(); System.out.println("退出Around方法"); return proceed; } @After("serviceAspect()") public void after(){ System.out.println("进入after方法"); } @Before("serviceAspect()") public void before(){ System.out.println("进入before方法"); } } 复制代码
TestService真正的业务类,例如输入插入/删除等,aop代理实现事物。
package lantao.aop; import org.springframework.stereotype.Service; /** * @Auther: lantao * @Date: 2019-05-09 13:59 * @Company: 随行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */ @Service public class TestService { @aspetJTest public void printInfo() { System.out.println("进入了printInfo方法"); } } 复制代码
TestAopMain就是测试类。
package lantao.aop; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.Arrays; import java.util.List; /** * @Auther: lantao * @Date: 2019-05-09 14:06 * @Company: 随行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */ public class TestAopMain { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring-bean-aop.xml"); TestService bean = classPathXmlApplicationContext.getBean(TestService.class); bean.printInfo(); } } 复制代码
Xml配置类,在其中有 aop:aspectj-autoproxy/ 标签,使Aop生效, context:component-scan/ 开启注解扫描。
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <aop:aspectj-autoproxy/> <!-- use-default-filters 属性的默认值为 true,即使用默认的 Filter 进行包扫描,而默认的 Filter 对标有 @Service,@Controller,@Component和@Repository 的注解的类进行扫描 --> <context:component-scan base-package="lantao.aop" use-default-filters="false"> <!-- 只扫描 base-package 的 controller 注解 还有对应的 exclude-filter 标签 排除 ; use-default-filters="false" 和 include-filter 一起使用 和 exclude-filter一起回抛异常--> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan> </beans> 复制代码
以上代码的执行结果
进入Around方法 进入before方法 进入了printInfo方法 退出Around方法 进入after方法 复制代码
在执行TestAopMain类中的main方法时,发现getBean方法返回的并不是目标类,而是目标类的 代理类
这里直接从 DefaultBeanDefinitionDocumentReader 类的 doRegisterBeanDefinitions 方法开始讲解,因前边都是xml解析的代码,已经在 Spring源码之XmlBeanFactory 中讲过了,其中 parseBeanDefinitions 方法是做标签解析使用的
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate){ //验证xml namespace, BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { //对默认标签处理 // 这里只处理 nade namespace 为 http://www.springframework.org/schema/beans 的标签 parseDefaultElement(ele, delegate); } else { //对自定义标签处理 非namespace 为 http://www.springframework.org/schema/beans 的标签 ,会解析 <context:component-scan base-package="lantao.scan"/> 或者自定义 dubbo // 或者 aop delegate.parseCustomElement(ele); } } } } else { //对自定义标签处理 delegate.parseCustomElement(root); } } 复制代码
这里直接关注 parseCustomElement 方法, parseDefaultElement 方法处理的是bean标签。
@Nullable public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } @Nullable public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { // 获取node的 NameSpaceURI String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 解析自定义标签 需要在 Meta-inf 文件加 增加 spring.handlers 文件 例如:http/://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler // 根据指定的 NameSpaceURI 获取 NamespaceHandler handler可以参考spring.handlers文件 // abstract NamespaceHandlerSupport 实现了 NamespaceHandler 接口,继而实现了 NamespaceHandler 的两个个方法(parser,docreate),自定义handler 需要实现 NamespaceHandlerSupport 类 // 进行 NamespaceHandler 类的 init 方法的 实现, 主要是做注册 BeanDefinitionParser( registerBeanDefinitionParser ) , 需要自定义解析类 继承 BeanDefinitionParser 类 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } // 解析操作 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } 复制代码
这里主要的工作就是机械 NamespaceHandler ,这里通过 NamespaceHandlerResolver的resolve方法 来解析各种 NamespaceHandler , 最后进行调用解析类的parse方法进行解析 ,接下来看一下resolve方法
@Override @Nullable public NamespaceHandler resolve(String namespaceUri) { // 这里获取的是所有注册到 handlerMappings 中的 NamespaceHandler , // 就是 resource/META-INF/spring.handler 中的 key就是namespaceUri , // 这些类都继承了 NamespaceHandlerSupport 实现了init方法 在init方法中进行 BeanDefinitionParse 的注册 Map<String, Object> handlerMappings = getHandlerMappings(); // 通过 namespaceUri 在 handlerMappings 中获取对应的处理器或者 className 如果是初始化过的就直接返回,反之进行类初始化工作 Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { // 实例化 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); // 判断实例化的类的超类或者超级接口 是否是 NamespaceHandler if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); // 注册 自定义标签所对应的 解析策略类 解析策略类都继承了 BeanDefinitionParser ,比如 ComponentScanBeanDefinitionParser namespaceHandler.init(); // 放入缓存中 handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageError err) { throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } } 复制代码
在 resolve方法 中一共做了 两件事情
1: 调用 getHandlerMappings 方法解析 resources 中的 META-INF/spring.handlers 文件,读取 各种处理类 。
spring.handlers: http/://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler 复制代码
2:进行 处理类的实例化 操作,然后调用 处理类 的 init 方法, 进行解析类(Parser)的注册 ,并将 实例化的处理类进行缓存处理 ,以备下次使用。
@Override public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } 复制代码
resolve方法理解后在回到 主方法(parseDefaultElement) 中,在实例化和解析操作后,调用了 处理类的parse 方法
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); 复制代码
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 在 NamespaceHandlerSupport 中的 parser 集合中获取 BeanDefinitionParser 的实现类 进行 parser BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); } 复制代码
在 findParserForElement 方法中通过 标签(aspectj-autoproxy) 进行获取 对应的处理类(AspectJAutoProxyBeanDefinitionParser) , 处理类的注册在实例化处理类后调用init方法已经完成, 接下来看一下 解析类的 parse 方法。
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 注册 AnnotationAwareAspectJAutoProxyCreator AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); // 扩展BeanDefinition 处理 子节点 <aop:include/> extendBeanDefinition(element, parserContext); return null; } 复制代码
在解析**(parse) 方法中,首先是注册了 AnnotationAwareAspectJAutoProxyCreator 类,这个类是处理注解拦截的代理类,然后又扩展了刚刚注册的 AnnotationAwareAspectJAutoProxyCreator**,对xml中 aop:aspectj-autoproxy 标签的子节点 aop:include/ 进行了处理。
首先看一下注册AnnotationAwareAspectJAutoProxyCreator的代码
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 注册 AnnotationAwareAspectJAutoProxyCreator BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 处理 proxy-target-class 和 expose-proxy属性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // 注册 BeanComponentDefinition registerComponentIfNecessary(beanDefinition, parserContext); } 复制代码
这里分为三个步骤
1:通过调用 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法进行注册 AnnotationAwareAspectJAutoProxyCreator 类。
2:处理 aop:aspectj-autoproxy 标签的 proxy-target-class 和 expose-proxy 属性。
3:注册 BeanComponentDefinition ,就是对 AnnotationAwareAspectJAutoProxyCreator 的封装。具体作用后续补上
先来看第一步注册的源码
@Nullable private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } 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; } 复制代码
这里就没什么好说的,先判断一下是否已经注册,如果已经注册,则 判断优先级 ,如果已注册优先级高则直接结束,反之直接创建 RootBeanDefinition ,通过调用 DefaultListableBeanFactory的registerBeanDefinition方法进行bean注册 。
优先级判断代码
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3); static { // Set up the escalation list... APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } 复制代码
private static int findPriorityForClass(@Nullable String className) { for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) { Class<?> clazz = APC_PRIORITY_LIST.get(i); if (clazz.getName().equals(className)) { return i; } } throw new IllegalArgumentException( "Class name [" + className + "] is not a known auto-proxy creator class"); } 复制代码
注册说完了继续看一下对 proxy-target-class 和 expose-proxy 属性的处理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { if (sourceElement != null) { // 对标签 proxy-target-class 的处理,使用方法 <aop:config proxy-target-class = "true"> 或 <aop:aspectj-autoproxy proxy-target-class="true"/> 使用 // 其作用是 强制使用 CGLIB 代理,设置<aop:aspectj-autoproxy proxy-target-class="true"/> ,或需要使用CGLIB 和 @Aspectj自动代理支持 属性 <aop:aspectj-autoproxy proxy-target-class="true"/> // JDK动态代理需要至少实现一个借口 CGLIB 不需要实现接口 boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } // 对 expose-proxy 的处理 其作用是实现 目标对象内部方法调用可实现切面的增强 // 例如 例如 A类中 c方法 调用 A类中的 d方法是无法实时切面增强的,需要设置 <aop:aspectj-autoproxy expose-proxy="true"/> 例如 d 方法 有 @Transaction 注解则失效 boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } 复制代码
proxy-target-class属性的作用是强制使用 CGLIB 代理。
expose-proxy属性的作用是 目标对象内部方法调用可实现切面的增强 ,例如Test类中的A,B方法,A调用B方法进行数据库save操作,B方法上有**@Transactional 注解,如果A直接调用B方法则事物是不起作用的,需要设置 expose-proxy=true**,然后使用 ((A)AopContext.currentProxy()).b() 调用方式。
注册整体完成后,看一下主方法的 extendBeanDefinition 方法,扩展BeanDefinition。
private void extendBeanDefinition(Element element, ParserContext parserContext) { BeanDefinition beanDef = parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME); if (element.hasChildNodes()) { addIncludePatterns(element, parserContext, beanDef); } } private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) { ManagedList<TypedStringValue> includePatterns = new ManagedList<>(); NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if (node instanceof Element) { Element includeElement = (Element) node; TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name")); valueHolder.setSource(parserContext.extractSource(includeElement)); includePatterns.add(valueHolder); } } if (!includePatterns.isEmpty()) { includePatterns.setSource(parserContext.extractSource(element)); beanDef.getPropertyValues().add("includePatterns", includePatterns); } } 复制代码
extendBeanDefinition方法主要是对注册的 AnnotationAwareAspectJAutoProxyCreator 就行扩充,如果 aop:aspectj-autoproxy 标签还有子标签,也就是** aop:include/ 标签,则会作getPropertyValues.add的操作,这里的 aop:include/ 标签如果存在对于解析@Aspect标注的类时有一个match的动作,这里的内容会在 buildAspectJAdvisors**方法中详细讲解。 好了到这里整个Xml的解析注册就完成了,接下来看一下具体的实现。
ClassFilter
用于约束一个 Advisor(通知器)
,与指定的 targetClass
是否匹配,只有匹配的前提下, Advisor
才能使用其内部持有的 Advice(增强器)
对 targetClass
进行增强。
Advisor 分两大类: IntroductionAdvisor (引介通知器)和 PointcutAdvisor (切点通知器)。两类 Advisor 都是为了增强 targetClass ,但是作用不一样。 IntroductionAdvisor 主要为了给 targetClass 追加接口(或者说追加更多的方法),这种增强属于 类级别
的增强;而 PointcutAdvisor 主要为了拦截方法,这种增强属于 方法级别
的增强。
正是由于两类Advisor的增强级别不同,而导致了对 ClassFilter 的使用方式不同。 IntroductionAdvisor 进行类级别增强,因此只需要直接持有 ClassFilter 即可;而 PointcutAdvisor 进行方法级别增强,因此需要同时使用 ClassFilter 和 MethodMatcher (方法匹配器)。PointcutAdvisor内部持有一个 Pointcut ,而 Pointcut就是由ClassFilter和MethodMatcher组成的 。
在上面的xml解析 aop:aspectj-autoproxy 标签时,一直都在说注册 AnnotationAwareAspectJAutoProxyCreator ,其实它是继承了 InstantiationAwareBeanPostProcessor -> BeanPostProcessor 的,继承了 InstantiationAwareBeanPostProcessor 会在 实例化之前执行
postProcessBeforeInstantiation 和 postProcessAfterInstantiation 方法,但同时它也 间接性
继承了 BeanPostProcessor ,也会在 初始化前后执行
postProcessBeforeInstantiation 和 postProcessAfterInitialization 方法,在 createBean 方法中有这么一方法 resolveBeforeInstantiation ,它就是在 实例化
之前执行的 InstantiationAwareBeanPostProcessor ,代码如下:
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ************ try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 给BeanPostProcessors一个返回代理而不是目标bean实例的机会 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } ********** } 复制代码
创建代理的真正方法就是 AbstractAutoProxyCreator.postProcessAfterInitialization 方法或 postProcessBeforeInstantiation 方法。 AbstractAutoProxyCreator 是 AnnotationAwareAspectJAutoProxyCreator 的超类。下面先看一下 AbstractAutoProxyCreator.postProcessBeforeInstantiation 方法
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); // 判断beanName是否为空 和 targetSoucedBeans是否包含beanName if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } // isInfrastructureClass:是否是基础架构类 就是是否是 aop配置类, 如果是 则不可代理这种 // shouldSkip 这里通过调用子类 AspectJAwareAdvisorAutoProxyCreator 的 shouldSkip 方法,通过获取全部的Advisor,来判断Advisor所属的bean和入参bean是否是同一个,如果是则不用增强反之可以, // 然后会调用 super.shouldSkip 排除 bean 名称 尾部是 .ORIGINA 结尾的bean 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. // 如果有自定义的targetSouce 在这里就直接创建代理,不需要等到实例化的时候在创建,避免不必要的bean创建实例化 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { // 缓存 this.targetSourcedBeans.add(beanName); } // 获取该bean可用的增强器 就是循环扫描配置类 , 扫出所有的 before alter around 等 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 根据增强器创建代理 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); // 缓存 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; } 复制代码
在 postProcessBeforeInstantiation
方法主要做了一下几件事情:
1: 判断 beanName 是否为空 和 targetSoucedBeans 是否包含 beanName 。
2: 判断是否是基础架构类,就是是否是aop配置类, 如果是则不可代理这种,直接返回,还会在判断 shouldSkip ,这里通过调用子类 AspectJAwareAdvisorAutoProxyCreator 的 shouldSkip 方法,通过获取全部的 Advisor ,来判断 Advisor 所属的 bean 和入参 bean 是否是同一个,如果是**(如果是则就是代表该bean是配置类) 则不可以增强反之可以,然后会调用 super.shouldSkip 排除尾部是 .ORIGINA 结尾的 bean**。
3: 获取自定义的TargetSouce ,如果存在就直接创建代理,不需要等到实例化的时候在创建,避免不必要的bean创建实例化。
4: 如果存在自定义的TargetSouce,则获取该bean可用的增强器 就是循环扫描配置类 , 扫出所有的 before alter around ,找到符合该bean的增强器。
5: 根据查询出来的增强器创建代理并返回。
上述是对存在 TargetSource 情况的描述,下面我们看一下不存在的情况
接下来看 AbstractAutoProxyCreator 类中的 postProcessAfterInitialization 方法
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); //防止 bean 多次被增强。 if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 如果需要 则创建代理 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } 复制代码
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 判断是否是 基础配置类或需要跳过的类。如果是则不增强 在下边的方法中会put if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // isInfrastructureClass:是否是基础架构类 就是是否是 aop配置类, 如果是 则不可代理这种 // shouldSkip 这里通过调用子类 AspectJAwareAdvisorAutoProxyCreator 的 shouldSkip 方法,通过获取全部的Advisor,来判断Advisor 所属的 bean 和入参 bean 是否是同一个,如果是则不用增强反之可以, // 然后会调用 super.shouldSkip 排除 bean 名称 尾部是 .ORIGINA 结尾的bean 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) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理并返回 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 增加缓存 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } // 增加缓存 如果不符合则话put,在上边的判断直接返回 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } 复制代码
1: 判断是否是 基础配置类或需要跳过的类。
2: 判断是否是基础架构类,就是是否是aop配置类, 如果是则不可代理这种,直接返回,还会在判断 shouldSkip ,这里通过调用子类 AspectJAwareAdvisorAutoProxyCreator 的 shouldSkip 方法,通过获取全部的 Advisor ,来判断 Advisor 所属的 bean 和入参 bean 是否是同一个,如果是**(如果是则就是代表该bean是配置类) 则不可以增强反之可以,然后会调用 super.shouldSkip 排除尾部是 .ORIGINA 结尾的 bean**。
3: 获取该bean符合的增强器。
4: 创建代理并返回。
5: 增加缓存。
6: 增加缓存 如果存在可用的增强器,则将该bean设置为false,在1中会进行判断。
在 wrapIfNecessary 中最重要的方法就是 getAdvicesAndAdvisorsForBean 方法,通过 getAdvicesAndAdvisorsForBean 方法可以获取到适合 bean增强器 ,接下来就看看它吧。
@Override @Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 获取该bean可以使用的增强器 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } 复制代码
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 获取所有增强器 List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 获取当前bean可以使用的增强器 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } 复制代码
在 findEligibleAdvisors 方法中首先获取了 所有的增强器 ,然后获取适合bean的增强器,先看一下 findCandidateAdvisors 方法。
这里首先执行 子类
的 findCandidateAdvisors 方法,也就是 AnnotationAwareAspectJAutoProxyCreator 的。
@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 调用父类 findCandidateAdvisors 方法 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { // 处理注解形式的 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } 复制代码
在这里首先调用了 父类
的 findCandidateAdvisors 方法,也就是处理 xml形式的Aop配置 ,然后执行了 buildAspectJAdvisors 方法,处理 注解形式的aop配置 。
先看一下父类的findCandidateAdvisors方法
protected List<Advisor> findCandidateAdvisors() { Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); return this.advisorRetrievalHelper.findAdvisorBeans(); } 复制代码
public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. // 获取缓存的 aop配置类名字,也就是 advisorBeanNames 数组中的信息 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! // 如果 cachedAdvisorBeanNames 不存在则通过BeanFactoryUtils 获取,条件是 根据类型获取 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } // 如果不存在配置类则返回空数组 if (advisorNames.length == 0) { return new ArrayList<>(); } // 反之理解析 List<Advisor> advisors = new ArrayList<>(); for (String name : advisorNames) { // 是否是有资格的bean if (isEligibleBean(name)) { // bean是否正在创建 if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isTraceEnabled()) { logger.trace("Skipping currently created advisor '" + name + "'"); } } else { try { // 存入到advisors中 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isTraceEnabled()) { logger.trace("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; } 复制代码
父类方法中主要做了两件事:
1: 首先先从缓存 cachedAdvisorBeanNames 中获取,看是否存在 Aop的配置类 ,如果不存在则通过 BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false) 方法获取Aop的配置类,赋值到缓存中。
2:循环解析 BeanName ,通过 beanFactory.isCurrentlyInCreation 方法判断 beanName 是否是正在创建状态,如果不是则add到advisors中。
接下来看一下 buildAspectJAdvisors 方法, 处理注解形式aop的配置类
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new ArrayList<>(); aspectNames = new ArrayList<>(); // 获取所有的bean String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); // 循环所有的bean 来获取增强器 for (String beanName : beanNames) { // 判断bean是否有资格 默认所有bean都是有资格的 也可以配置 正则表达式 来判断哪些@aspet bean 是资格的 // 检查给定的bean是否有资格进行自动代理。 // 如果没有使用<aop:include>元素,则将 includePatterns null 并指定所有bean都是有资格的。如果“includePatterns”为非null,则需要和include中的name机型匹配。 // 例如 @Aspect标注的类是 config <aop:include name="config1"/> include的name是 config1 则不匹配, 则@Aspect标注的不生效 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的type Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 判断是否是 aop配置bean 也就是是否被@Aspect注解标注 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); // 构建成AspectMetadata类 AspectMetadata amd = new AspectMetadata(beanType, beanName); // 判断@Aspect注解中标注的是否为singleton类型,默认的切面类都是singleton类型 if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 获取增强器 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); // put cache if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } // add advisors 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<Advisor> advisors = new ArrayList<>(); for (String aspectName : aspectNames) { List<Advisor> 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; } 复制代码
在 buildAspectJAdvisors 方法中,主要做了以下事情:
1: 首先获取所有的bean,通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false)。
2: 判断bean是否有资格,默认所有bean都是有资格的,也可以通过配置 includePatterns
来判断哪些@aspet bean 是资格的。
使用 aop:include/ 标签,如果配置 aop:include/ 元素, includePatterns 为非null,则需要和include中的name机型匹配。
如果不配置,则 includePatterns 为 null 并指定所有bean都是有资格的。
例如 @Aspect 标注的类是 config <aop:include name="config1"/> include的name是 config1 则不匹配, 则@Aspect标注的不生效。
3: 判断bean是否是Aop配置类,也就是是否被@Aspect标识。
5: 返回全部增强器, 其中2 3 4 5都是for循环中操作。
在 buildAspectJAdvisors 方法中,最重要的就是 步骤4
,获取每一个 bean 的增强器,接着看 this.advisorFactory.getAdvisors(factory) 方法:
@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { // 获取 @Aspect 标注Bean 类型 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); // 获取 @Aspect 标注Bean 名字 String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); // 进行bean验证 validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); // 获取除了 标记有 Pointcut 注解 的所有方法 for (Method method : getAdvisorMethods(aspectClass)) { // 获取每个方法上的 增强器 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { // add advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; } 复制代码
在 getAdvisors 方法中,通过 getAdvisorMethods 方法获取到了除了标记有 Pointcut 注解的其他所有方法,然后通过 getAdvisor 方法获取每个 方法 上的增强器。
private List<Method> getAdvisorMethods(Class<?> aspectClass) { final List<Method> methods = new ArrayList<>(); // 获取除了 标记有 Pointcut 注解 的所有方法 ReflectionUtils.doWithMethods(aspectClass, method -> { // Exclude pointcuts if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { methods.add(method); } }); methods.sort(METHOD_COMPARATOR); return methods; } 复制代码
@Override @Nullable public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { // 验证 validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 获取切点 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // 实例化 增强器 这里使用的是PointcutAdvisor通知器,是方法级别的 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); } 复制代码
在 getAdvisor 方法中首先做了 bean类型的验证 ,然后获取 切点 ,最后开始 实例化增强器, 这里实例化增强器使用的是PointcutAdvisor(通知器),实际上InstantiationModelAwarePointcutAdvisorImpl是PointcutAdvisor的一个实现,也就是 方法级别
的通知器 。
@Override public void validate(Class<?> aspectClass) throws AopConfigException { // If the parent has the annotation and isn't abstract it's an error // 是否存在@Aspect注解 和 abstract判断 if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null && !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) { throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" + aspectClass.getSuperclass().getName() + "]"); } AjType<?> ajType = AjTypeSystem.getAjType(aspectClass); // 判断bean类型是否是 Aspect if (!ajType.isAspect()) { throw new NotAnAtAspectException(aspectClass); } // 判断 bean 的 kind 是否是 PERCFLOW PERCFLOWBELOW 这两种在AOP中是不支持的 if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) { throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " + "This is not supported in Spring AOP."); } if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) { throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " + "This is not supported in Spring AOP."); } } 复制代码
@Nullable private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 获取 判断增强器类型 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 构建 AspectJExpressionPointcut 类 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; } 复制代码
通过 findAspectJAnnotationOnMethod 方法获取到方法的增强器类型,然后构建 AspectJExpressionPointcut 类,
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { this.declaredPointcut = declaredPointcut; this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); this.methodName = aspectJAdviceMethod.getName(); this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); this.aspectJAdviceMethod = aspectJAdviceMethod; this.aspectJAdvisorFactory = aspectJAdvisorFactory; this.aspectInstanceFactory = aspectInstanceFactory; this.declarationOrder = declarationOrder; this.aspectName = aspectName; if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; // 实例化增强器 this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } } 复制代码
在这里主要关注 instantiateAdvice 方法,实际上它的作用就是 实例化Advice :
@Override @Nullable public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { // 获取 @Aspect 标注de bean的类型 Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); // 验证bean validate(candidateAspectClass); // 获取方法上的增强器 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // If we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class // 检查 bean 是否是被 @Aspect标注 if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; // 实例化 增强器 根据不同的类型实例化不通过的增强器 switch (aspectJAnnotation.getAnnotationType()) { case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; case AtAround: springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } // Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; } 复制代码
首先这里还是会首先 验证bean的类型 ,通过 validate 方法,接下来获取 method 的增强器,依然是通过 findAspectJAnnotationOnMethod 方法,紧接着判断 bean是否被@Aspect标注 ,最后通过 switch 语法 实例化增强器 并赋值一些参数配置。
到这里我们已经 获取到了上下文中所有的可用增强器 ,到此 findCandidateAdvisors 方法的代码就全部都解析完成了,如果还没有明白整体流程,可以看一下下方 时序图 。
接下来根据解析到的 增强器进行匹配 ,查找出适用于需要 实例化bean的增强器 , findAdvisorsThatCanApply 方法源码:
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { // 设置当前代理对象名称 ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 匹配 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { // 删除当前代理对象名称 ProxyCreationContext.setCurrentProxiedBeanName(null); } } 复制代码
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { // 在这里对 IntroductionAdvisor 类型的 Advisor(通知器)做会处理, 因为IntroductionAdvisor 是处理类拦截级别的 // 仅需要使用classFilter 即可 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { // 对 处理过Advisor 的做 跳过处理 if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 在这里对 PointcutAdvisor 类型的 Advisor(通知器) 进行处理,因为 PointcutAdvisor 是方法级别的拦截,需要做 ClassFilter 和 MethodMatcher 判断 if (canApply(candidate, clazz, hasIntroductions)) { // 将匹配的增强器 add eligibleAdvisors.add(candidate); } } // 返回bean匹配的增强器 return eligibleAdvisors; } 复制代码
在上述代码中,可以看到,这里会对 Advisor(通知器) 做判断处理,分别是 IntroductionAdvisor 和 PointcutAdvisor ,他们都分别继承了 Advisor , 在本文中是使用 PointcutAdvisor 的实现类 InstantiationModelAwarePointcutAdvisorImpl 。
IntroductionAdvisor: IntroductionAdvisor 主要为了给 targetClass 追加接口(或者说追加更多的方法),这种增强属于 类级别
的增强,所以只需要做 ClassFilter 判断。
PointcutAdvisor: PointcutAdvisor 主要为了拦截方法,这种增强属于 方法级别
的增强,则需要做 ClassFilter 和 MethodMatcher 的判断。
在findAdvisorsThatCanApply方法中最重要的就是canApply方法,直接看一下源码:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); // 首先ClassFilter 进行匹配 if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); // 循环匹配每一个方法 for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; } 复制代码
在canApply方法中首先做了 ClassFilter的匹配 判断,接下来获取到Class的全部public方法,遍历所有方法,进行MethodMatcher的 匹配操作 ,最终将匹配到的 Advisor 全部返回,到这里 findAdvisorsThatCanApply 方法就全部解析完成了。
在 5.2 中已经将适配于bean的增强器(Advice)获取到了, 接下来继续分析主流程 wrapIfNecessary 方法中的 createProxy 方法。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { // 曝光 目标类 if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); // 判断 是否设置了 ProxyTargetClass 是否使用CGLIB if (!proxyFactory.isProxyTargetClass()) { // 如果没有设置 ProxyTargetClass 则需要判断 beanClass 是否应该使用CGLIB 反之使用 JDK动态代理 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } // 设置bean的增强器和拦截器 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()); } 复制代码
上面的方法其实就是封装了 ProxyFactory ,真是创建代理的还是 ProxyFactory ,接下来看一下getProxy接口。
public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } 复制代码
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 判断使用 CGLIB 还是 JDK动态代理 // isOptimize : 是否优化处理 // isProxyTargetClass 是否使用CGLIB代理 // hasNoUserSuppliedProxyInterfaces 是否实现了接口 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // 如果是实现了接口 则 使用JDK代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 使用CGLIB代理 return new ObjenesisCglibAopProxy(config); } else { // 使用JDK代理 return new JdkDynamicAopProxy(config); } } 复制代码
接下来就是调用getProxy方法进行CGLIB或者JDK代理创建了,然后返回代理类。
CBLIB 和 JDK 代理源码后续文章讲解。
GItHub : github.com/lantaoGitHu…
参考: my.oschina.net/lixin91/blo…