Spring Aop实现原理

文章目录

一、AOP的使用

1.1 基于XML

示例:
定义切面:

public class MyAspectXML {

    public void before(){
        System.out.println("MyAspectXML====前置通知");
    }

    public void afterReturn(Object returnVal){
        System.out.println("后置通知-->返回值:"+returnVal);
    }

    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("MyAspectXML=====环绕通知前");
        Object object= joinPoint.proceed();
        System.out.println("MyAspectXML=====环绕通知后");
        return object;
    }

    public void afterThrowing(Throwable throwable){
        System.out.println("MyAspectXML======异常通知:"+ throwable.getMessage());
    }

    public void after(){
        System.out.println("MyAspectXML=====最终通知..来了");
    }
}

配置XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--<context:component-scan base-package=""-->

    <!-- 定义目标对象 -->
    <bean name="productDao" class="com.zejian.spring.springAop.dao.daoimp.ProductDaoImpl" />

    <!-- 定义切面 -->
    <bean name="myAspectXML" class="com.zejian.spring.springAop.AspectJ.MyAspectXML" />
    <!-- 配置AOP 切面 -->
    <aop:config>
        <!-- 定义切点函数 -->
        <aop:pointcut id="pointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.add(..))" />

        <!-- 定义其他切点函数 -->
        <aop:pointcut id="delPointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.delete(..))" />

        <!-- 定义通知 order 定义优先级,值越小优先级越大-->
        <aop:aspect ref="myAspectXML" order="0">
            <!-- 定义通知
            method 指定通知方法名,必须与MyAspectXML中的相同
            pointcut 指定切点函数
            -->
            <aop:before method="before" pointcut-ref="pointcut" />

            <!-- 后置通知  returning="returnVal" 定义返回值 必须与类中声明的名称一样-->
            <aop:after-returning method="afterReturn" pointcut-ref="pointcut"  returning="returnVal" />

            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pointcut"  />

            <!--异常通知 throwing="throwable" 指定异常通知错误信息变量,必须与类中声明的名称一样-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="throwable"/>

            <!--
                 method : 通知的方法(最终通知)
                 pointcut-ref : 通知应用到的切点方法
                -->
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

1.2 基于注解

示例:
切面类:

@Aspect
public class MyAspect {

    /**
     * 前置通知
     */
    @Before("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
    public void before(){
        System.out.println("前置通知....");
    }

    /**
     * 后置通知
     * returnVal,切点方法执行后的返回值
     */
    @AfterReturning(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",returning = "returnVal")
    public void AfterReturning(Object returnVal){
        System.out.println("后置通知...."+returnVal);
    }


    /**
     * 环绕通知
     * @param joinPoint 可用于执行切点的类
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知前....");
        Object obj= (Object) joinPoint.proceed();
        System.out.println("环绕通知后....");
        return obj;
    }

    /**
     * 抛出通知
     * @param e
     */
    @AfterThrowing(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",throwing = "e")
    public void afterThrowable(Throwable e){
        System.out.println("出现异常:msg="+e.getMessage());
    }

    /**
     * 无论什么情况下都会执行的方法
     */
    @After(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
    public void after(){
        System.out.println("最终通知....");
    }
}

配置文件,开启自动配置:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 启动@aspectj的自动代理支持-->
    <aop:aspectj-autoproxy />

    <!-- 定义目标对象 -->
    <bean id="userDaos" class="com.zejian.spring.springAop.dao.daoimp.UserDaoImp" />
    <!-- 定义aspect类 -->
    <bean name="myAspectJ" class="com.zejian.spring.springAop.AspectJ.MyAspect"/>
</beans>

除了使用配置文件的<aop:aspectj-autoproxy />开启之外,也可以通过在配置类上增加@EnableAspectJAutoProxy注解即可。或者直接使用@Bean注解,在标注该注解的方法中,创建一个AnnotationAwareAspectJAutoProxyCreator的类实例。

二、@AspectJ形式的AOP实现原理

无论使用XML文件配置还是使用注解,自动织入AOP的实现都依赖于AnnotationAwareAspectJAutoProxyCreator类。该类实现了BeanPostProcessor接口,在类初始化完毕后会对每个Bean进行判断,并决定是否进行织入。如果需要织入,则使用JDK动态代理或者cglib动态代理生成对应的代理类,并替换原来的Bean。

而不管是在XML文件中配置<aop:aspectj-autoproxy />语句,还是在配置类上添加@EnableAspectJAutoProxy注解,其核心都是将AnnotationAwareAspectJAutoProxyCreator类添加到Spring容器中。

2.1 < aop:aspectj-autoproxy />

< aop:aspectj-autoproxy />语句的解析由AspectJAutoProxyBeanDefinitionParser类完成的,该类的主要作用就是在Spring容器中注册AnnotationAwareAspectJAutoProxyCreator类对应的BeanDefinition。

2.2 @EnableAspectJAutoProxy

该注解通过@Import注解,引入了AspectJAutoProxyRegistrar类。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
 
	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 此处向容器注入了AnnotationAwareAspectJAutoProxyCreator类
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
 
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
 
}

该类的作用同样是向Spring容器中注册AnnotationAwareAspectJAutoProxyCreator

2.3 AnnotationAwareAspectJAutoProxyCreator的处理过程

该类的抽象父类AbstractAutoProxyCreator实现了BeanPostProcessor接口。核心逻辑都在抽象父类中,AnnotationAwareAspectJAutoProxyCreator的处理过程重写了父类的findCandidateAdvisors()方法,加入了对@Aspect注解锁标记的切面的扫描。
其父类实现的postProcessBeforeInstantiation在所有Bean实例化之前,就将所有的Advise切面类都加载完成,并放到一个容器AdviseBeans中。
其父类实现的postProcessAfterInitialization方法则在所有Bean实例化之后,对所有Bean进行判断是否需要增强,如果需要则从Advise容器中找出匹配的切面,然后使用动态代理进行增强。

AbstractAutoProxyCreator源码:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
 
    @Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
 
		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			//shouldSkip方法调用findCandidateAdvisors()方法加载切面
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}
 
		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			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;
	}
 
    // 生成代理对象
    @Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
 
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
        // 跳过基础设施类
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
        // 跳过基础设施类
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
 
		// Create proxy if we have advice.
        // 获取切面Advisor
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
 
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
 
    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);
 
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
                // 解析目标对象接口
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
 
        // 生成Advisor
		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());
	}
 
}

AnnotationAwareAspectJAutoProxyCreator源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.aop.aspectj.annotation;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.Assert;

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
    private List<Pattern> includePatterns;
    private AspectJAdvisorFactory aspectJAdvisorFactory;
    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    public AnnotationAwareAspectJAutoProxyCreator() {
    }

    //....其他代码

    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.initBeanFactory(beanFactory);
        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }

        this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }
//重写了加载切面的方式,加载@Aspect注解所代表的切面
    protected List<Advisor> findCandidateAdvisors() {
        List<Advisor> advisors = super.findCandidateAdvisors();
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }

    protected boolean isInfrastructureClass(Class<?> beanClass) {
        return super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass);
    }

    protected boolean isEligibleAspectBean(String beanName) {
        if (this.includePatterns == null) {
            return true;
        } else {
            Iterator var2 = this.includePatterns.iterator();

            Pattern pattern;
            do {
                if (!var2.hasNext()) {
                    return false;
                }

                pattern = (Pattern)var2.next();
            } while(!pattern.matcher(beanName).matches());

            return true;
        }
    }

    private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
        public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
            super(beanFactory, advisorFactory);
        }

        protected boolean isEligibleBean(String beanName) {
            return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
        }
    }
}

3. 其他形式

参考:
https://blog.csdn.net/xiaoshuai1127/article/details/76221401
https://www.cnblogs.com/z00377750/p/11793088.html

上一篇:Spring三级缓存


下一篇:死磕Spring之IoC篇 - 单例 Bean 的循环依赖处理