本文主要介绍Spring的aop:aspectj-autoproxy/标签,了解spring是如何实现扫描注解进行aop的,主要实现是在 AspectJAutoProxyBeanDefinitionParser的parser方法中,另外这里php
还须要了解一下NamespaceHandler, NamespaceHandlerSupport 和 BeanDefinitionParser 的关系,若是不清楚的能够看一下Spring源码之ApplicationContext中的解释。java
在讲述aop源码以前,须要先了解一下 Jdk 动态代理和 CGLIB 代理的区别和使用。node
Jdk动态代理须要目标类至少实现一个接口,在运行时期生成代理类。git
CGLIB代理无需实现接口,经过生成类字节码实现代理,比反射稍快,不存在性能问题,但CGLIB会继承目标对象,须要重写方法,因此目标对象不能为final类。github
示例是基于注解形式,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注解的方法都会被代理。spring
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就是测试类。express
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方法是作标签解析使用的
DefaultBeanDefinitionDocumentReader . 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;
}
复制代码
来解析wrapIfNecessary方法都作了什么:
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 是资格的。
配置includePatterns:
使用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标识。
4: 经过this.advisorFactory.getAdvisors(factory)方法获取bean的加强器。
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方法获取每一个方法上的加强器。
getAdvisorMethods方法源码:
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;
}
复制代码
getAdvisor方法源码:
@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的一个实现,也就是方法级别
的通知器。
先看beanType的验证,validate方法源码:
@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.");
}
}
复制代码
接下来看获取加强器切点信息getPointcut方法源码:
@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…