Spring AOP源码分析(二)

无论是单例 Bean 还是原型 Bean ,对于AOP的实现其实就是依赖于 BeanPostProcessor 的回调,这里主要有个主要的实现类: SmartInstantiationAwareBeanPostProcessor ,这个类即实现了 BeanPostProcessor ,也实现了 InstantiationAwareBeanPostProcessor

Spring AOP源码分析(二)

InstantiationAwareBeanPostProcessor 提供了一个 postProcessorBeforeInstantiation 方法, BeanPostProcessor 提供了一个 postProcessorAfterInitialization 方法。

上面的类图可以看出来入口就是 AbstractAutoProxyCreator

1. AbstractAutoProxyCreator#postProcessBeforeInstantiation

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiationIOC实例Bean 之前会调用 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    //3.通过BeanPostProcessor返回代理Bean
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
        return bean;
    }
    
    //4.常规创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}
复制代码

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    //1.不需要创建代理
    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        //2.如果是基础设施或者应该跳过的类,则说明这个类不需要创建代理,缓存起来
        //默认shouldSkip是false,都不应该跳过
        //但是AspectJAwareAdvisorAutoProxyCreator实现了该方法
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    //2.对于自定义的TargetSource会立即创建代理,并缓存
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        //如果不是TargetSource,一般不会走到这里
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    return null;
}
复制代码

这个方法是在 Bean Instance 之前,判断当前这个 Bean 是否需要生成代理,如果是AOP的基础设施类或者应该跳过的类,则不生成代理;如果是自定义的 targetSource ,则立即生成代理。

因为 AspectJAwareAdvisorAutoProxyCreator 实现了 shouldSkip 方法,而且 AspectJAwareAdvisorAutoProxyCreator 是由 <aop:config/> 转换而来,也就是针对XML的,那也可以说注解方式都不跳过。

shouldSkip 默认是false,即所有的 Bean 都不跳过,现在看下 AspectJAwareAutoProxyCreator 的实现:

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    //1.获取所有的Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        //对于<aop:aspect/>中的<aop:before/>类似的生成的是AspectJPointcutAdvisor
        //Advice就是AbstractAspectJAdvice的子类
        if (advisor instanceof AspectJPointcutAdvisor) {
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                return true;
            }
        }
    }
    return super.shouldSkip(beanClass, beanName);
}
复制代码

这个方法获取IOC容器中所有的候选切面,如果 advisorAspectJPointcutAdvisor 并且 advice 是当前类,则返回true,应该跳过,否则调用父类的方式,返回false,不跳过。

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
    //调用一个工具类
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
复制代码

org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

public List<Advisor> findAdvisorBeans() {
    //1.缓存的通知器的名称
    String[] advisorNames = this.cachedAdvisorBeanNames;
    //2.如果cachedAdvisorBeanNames为空,则到容器中查找
    //并设置缓存,后续直接使用缓存即可
    if (advisorNames == null) {
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<Advisor>();
    }

    List<Advisor> advisors = new ArrayList<Advisor>();
    //3.遍历所有的通知器
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            //4.忽略正在创建的advisor
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                //5.从容器中获取Advisor,并添加到advisors中,在这个时候Advisor就被实例化了
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
        }
    }
    return advisors;
}
复制代码

通过一个帮助类 BeanFactoryAdvisorRetrievalHelper 来获取 Advisor ,首先从缓存中获取 advisorNames ,如果不存在则根据类型获取 advisorNames 并放入缓存,然后通过遍历 advisorNames ,从容器中获取 bean ,当然这里如果要获取的 bean 还未被实例化,则会进行实例化,最后返回所有的 Advisor 。这里会忽略 FactoryBean 和正在创建的 Advisor

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getCustomTargetSource

protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
    if (this.customTargetSourceCreators != null &&
        this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
        for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
            TargetSource ts = tsc.getTargetSource(beanClass, beanName);
            if (ts != null) {
                return ts;
            }
        }
    }
    return null;
}
复制代码

从容器中获取自定义的 TargetSource ,一般默认都是使用 SingletonTargetSource

如果不需要跳过,则根据自定义的 TargetSource 立即创建代理, TargetSource 被用来执行 MethodInvocation 的时候获取真正的 target 。所以, proxy 代理的并不是 target ,而是 targetSource

通常情况下,一个代理对象只能代理一个 target ,每次调用目标方法也是唯一的 target 。但是如果让 proxy 代理 targetSource ,可以是的每次调用的 target 实例都不同。当然这取决于 targetSource 的实现,这种机制,使得方法的调用更加灵活。

1.查找通知

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected abstract Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;
复制代码

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
    //1.查找合适的通知器
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}
复制代码

获取合适的通知器。

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //1.查找所有的通知器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //2.筛选可以在该bean上应用的通知器,通过ClassFilter和MethodMatcher对目标类和方法进行匹配
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    //3.扩展操作
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
复制代码

获取合适的通知器,主要分为3步:1.查找所有的通知;2.过滤通知;3.扩展通知。

Spring AOP源码分析(二)

获取通知主要有两种方式:1.基于XML;2.基于注解。

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors 这个方法在 shouldSkip 的时候已经执行过了,就是根据所有的 advisorNames 获取所有的 Advisor ,因为 shouldSkip 的时候已经创建过了 advisor bean ,所以这里 getBean 的时候可以直接拿到。

Spring AOP源码分析(二)

对于注解的,其实就是多调用了一个方法从容器中获取被 @Aspect 注解的类。

@Override
protected List<Advisor> findCandidateAdvisors() {
    //1.调用父类方法查找所有的通知
    List<Advisor> advisors = super.findCandidateAdvisors();
    //2.解析@Aspect注解,并构建通知
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}
复制代码

在调用 AspectJAwareAdvisorAutoProxyCreator#findCandidateAdvisors 获取所有xml的之后,获取被 @Aspect 注解的类,并转为 Advisor

从这个结果可以看出来是使用 AspectJPonitcutAdvisor ,其内部包含了 AdvicePointcutOrder ,也就意味着现在拿到了整个应用程序中所有的切面。

2.过滤通知

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#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);
    }
}
复制代码

通过一个线程单例进行过滤符合当前Bean的切面。

org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
    for (Advisor candidate : candidateAdvisors) {
        //1.筛选IntroductionAdvisor的通知器
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        //2.筛选普通类型通知器
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}
复制代码

org.springframework.aop.support.AopUtils#canApply

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        //1.从通知器中获取ClassFilter,并调用matches进行匹配
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        //2.对于普通Advisor,这里继续调用重载方法进行筛选
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        return true;
    }
}
复制代码

org.springframework.aop.support.AopUtils#canApply

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		//1.使用ClassFilter匹配Class
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		//2.查找当前类及其父类的所有Class,只要有一个方法符合,就说明该切面是适用于当前bean的
		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			//3.获取当前类的方法列表,包括从父类继承而来的
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				//4.使用methodMatcher匹配方法,匹配成功立即返回
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}
复制代码

上述源码表示了按照切点(Pointcut)对切面(Advisor)的过滤的一个过程,这里有两个重要的类:1. ClassFilter ;2. MethodMatcherClassFilter 用于根据切点过滤类, MethodMatcher 用于根据切点过滤类的方法,只要某个类中的某个方法符合,那么就说明该切面适用于该 Bean

3.通知扩展

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#extendAdvisors

protected void extendAdvisors(List<Advisor> candidateAdvisors) {
}
复制代码

默认是一个空实现,交由子类实现。

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#extendAdvisors

/**
* 将{@link ExposeInvocationInterceptor}添加到通知责任链的开头
* 当使用AspectJ表达式切点和AspectJ样式的通知的时候,这是必须的
*/
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
复制代码

org.springframework.aop.aspectj.AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary

/**
* 增加特定的通知器到通知责任链头部,如果责任链包含AspectJ通知器
* 如果不包含AspectJ通知器,则无效
* 目的是暴露当前AOP的调用链,确保JoinPoint可用
*/
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // Don't add advisors to an empty list; may indicate that proxying is just not required
    // 1.如果通知器列表是一个空列表,则啥都不做
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        //2.用于检测advisors列表中是否存在AspectJ类型的Advisor或Advice
        for (Advisor advisor : advisors) {
            // Be careful not to get the Advice without a guard, as
            // this might eagerly instantiate a non-singleton AspectJ aspect
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
            }
        }

        //3.向advisors列表的首部添加DefaultPointcutAdvisor
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}
复制代码

增加 ExposeInvocationInterceptor 这个拦截器为第一个执行的作用是使用一个线程单例保存了 MethodInvocation ,这个 MethodInvocation 其实就是执行通知和目标方法的对象,当有其他的地方需要这个 MethodInvocation 的时候,就可以通过 ExposeInvocationInterceptor#currentInvocation 获取。

4.创建代理

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

protected Object createProxy(
    Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    //1.默认情况下,proxy-target-class=false,使用jdk动态代理
    if (!proxyFactory.isProxyTargetClass()) {
        //判断proxy-target-class属性
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            //2.检查目标类是否实现了接口,如没有,则设置proxy-target-class=true,使用cglib动态代理
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    //3.确保所有的都是Advisor
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    //4.创建代理
    return proxyFactory.getProxy(getProxyClassLoader());
}
复制代码

为目标对象创建代理类,首先需要判断 proxy-target-class ,这个属性已经看过很多次了,表达代理的方式,如果 proxy-target-class 为false,但是该类没有实现接口,那么也还是使用 CGLIB 代理;然后确保所有的拦截器都是 Advisor ;最后通过 ProxyFactory 创建代理类,并返回存在IOC容器中。

org.springframework.aop.framework.ProxyFactory#getProxy

public Object getProxy(ClassLoader classLoader) {
    //1.先创建AopProxy(DefaultAopProxyFactory会根据条件决定创建哪种AopProxy),然后再创建bean的代理
    return createAopProxy().getProxy(classLoader);
}
复制代码

org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    //1.是否需要优化||代理类型(前面已经设置过了)||是否实现了接口
    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.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        //2.使用cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        //3.使用jdk动态代理
        return new JdkDynamicAopProxy(config);
    }
}
复制代码
Spring AOP源码分析(二)

org.springframework.aop.framework.CglibAopProxy#getProxy

@Override
public Object getProxy(ClassLoader classLoader) {
    //1.从TargetSource获取target的class
    Class<?> rootClass = this.advised.getTargetClass();

    //2.判断是否已经是代理类了
    Class<?> proxySuperClass = rootClass;
    if (ClassUtils.isCglibProxyClass(rootClass)) {
        proxySuperClass = rootClass.getSuperclass();
        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
        for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
        }
    }

    //3.CGLIB
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

    //4.各种回调
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }

    //5.回调过滤
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    //6.创建代理实例
    return createProxyClassAndInstance(enhancer, callbacks);
}
复制代码

org.springframework.aop.framework.JdkDynamicAopProxy#getProxy

@Override
public Object getProxy(ClassLoader classLoader) {
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
复制代码

获取代理的两种方式:1.JDK;2.CGLIB。当执行AOP的时候,入口也是在这两个类。

2. AbstractAutoProxyCreator#postProcessAfterInitialization

Bean 实例化完成之后,就要执行初始化方法了,这个会调用 BeanPostProcessor 的初始化回调方法,在这里才会真正的生成代理对象,上面的 postProcessorBeforeInstantiation 是在 Bean 实例化之前执行,而且一般不会在这个方法中生成代理对象,而是在该方法中。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

/**
* bean初始化后置处理方法
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            //如果需要,为bean生成代理对象
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
复制代码

这就是AOP的入口,对于单例 Bean 会在预实例化的时候调用,拿到代理对象,并放入单例的缓存中;对于原型 Bean ,因为没有缓存,每一次调用 Bean 的时候都需要执行该方法判断是否需要生成代理对象。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

/**
* 是否需要为目标类生成代理类
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //1.这两个集合在postProcessorBeforeInitialization中生成的,这里可直接使用
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //2.如果是基础设施类(Pointcut、Advice、Advisor等的实现类),或是应该跳过的类
    //则不应该生成代理类,直接返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    //3.为目标Bean查找合适的通知和通知器
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //4.如果通知存在,则生成代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //5.创建代理
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    //6.通知不存在,直接返回bean
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}
复制代码

可以看到这个真正生成代理对象的方法,也是相同的步骤,调用相同的方法:1.判断基础设施( shouldSkip );2.查找通知( getAdvicesAndAdvisorsForBean );3.创建代理( createProxy )。与上面完全是一模一样的。

总结一下:

1.获取通知。从IOC容器中获取所有的 Advisor ,如果不存在,则创建。

2.过滤通知。根据 Pointcutexpression 通过 ClassFilterMethodMatcher 进行过滤,找到可以应用AOP的类及方法。

3.扩展通知。通过 ExposeInvocationInterceptor 的线程单例暴露执行的 MethodInvocation ,以便其他地方使用。

4.创建代理对象。根据 proxy-target-class 选择 JDK 动态代理还是 CGLIB 动态代理,如果 proxy-target-class 为false,但是该类未实现接口,那么依然会使用 CGLIB 动态代理。

原文 

https://juejin.im/post/5efda0325188252e382a4549

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring AOP源码分析(二)

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址