Spring源码阅读----Spring AOP使用和源码解析

概述

Spring经常被人提及的就是IOC和AOP,前边在介绍IOC的时候,我们已经提及到了AOP,还记得起来吗?
在《Spring源码阅读----Spring IoC之finishBeanFactoryInitialization(续)很重要的createBean》一文中,介绍到有些实现了InstantiationAwareBeanPostProcessor接口的AbstractAutoProxyCreator类,其子类AnnotationAwareAutoProxyCreator是个很重要的类。

啥是AOP

AOP(Aspect Oriented Programming),面向切面思想,可以百度一下其概念。比如日志打印等边缘需求会散落在多处业务中,重复写冗余代码会影响项目维护,而AOP就是将这类主业务以外的代码提取出来,使其分离,然后在这些业务中寻找切入点,然后将分离的非业务代码切入业务中。

实践一下

下面来看一个例子,在原来的SSM demo里改造

  1. 在pom文件中加入依赖包
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.5</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>
  1. 创建一个切面类AopTest
@Component
@Aspect
public class AopTest {
    
    @Pointcut("execution(* com.zhlab..ssm.demo.web.controller.TestController.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        System.out.println("前置通知before start");
        String methodName = joinPoint.getSignature().getName();
        System.out.println("前置通知before end");
    }

    @After("pointCut()")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("后置通知after start");
        String methodName = joinPoint.getSignature().getName();
        System.out.println("后置通知after end");
    }

    @Around("pointCut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知after start");
        String methodName = joinPoint.getSignature().getName();
        Object result = joinPoint.proceed();//执行业务具体业务逻辑
        System.out.println("环绕通知after end");
        return result;
    }
}

类上加上两个注解@Component、@Aspect
注解@Aspect表示当前类是一个切面,添加@Component注解表示当前类需要初始化一个bean到Spring容器中,这个类里只使用了@Before、@After、@Around三个方法注解,总的有以下几个注解:

  • @Before注解修饰方法表示当前方法会在连接点方法之前执行
  • @After注解修饰方法表示当前方法会在连接点之后执行
  • @Around注解修饰方法表示当前方法会在连接点之前和之后均会执行
  • @AfterThrowing注解修饰方法表示当前方法会在连接点抛异常之后执行,如果不抛异常则不会执行
  • @AfterReturning注解修饰方法表示当前方法会在连接点返回结果时执行,如果连接点方法是void,则该注解不会生效

@Pointcut后可以写execution和@Annotation
execution表达式里的各个号的含义:
"execution(
com.zhlab..ssm.demo.web.controller.TestController.*(..))"

  • 返回类型: 第一个 * 号的位置:表示返回值类型,* 表示方法返回类型无限制
  • 包名以及类:表示需要拦截的包名,TestController指定了具体的类,如果这里改成 ..* 则表示controller包以及其子包下的所有类
  • 方法: 第二个 * 号 表示 所有方法,后面括号里面表示方法的参数,两个句点表示任何参数

annotation() 表达式:
"@annotation(org.springframework.web.bind.annotation.GetMapping)"
然后使用该切面的话,就会切入注解是 @GetMapping的所有方法。这种方式很适合处理 @GetMapping、@PostMapping、@DeleteMapping等不同注解有各种特定处理逻辑的场景。

  1. 在配置文件中加入aop配置信息如下
    <!-- 主要这个信息需要加在spring mvc配置文件里 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  1. 启动项目,然后访问/test,效果如下:
aop demo

如果method有多个切面的话,我们可以使用@Order(1) 来排序,数字越小排前面。
好了其他的例子就不一一例举了。

很重要的AnnotationAwareAutoProxyCreator

小结

<aop:aspectj-autoproxy />标签的作用是声明自动为Spring容器中那些配置@Aspectj注解的切面的bean创建代理,织入切面
这个标签需要加到spring-mvc的配置代码中才起作用
(头部标签声明需要加入xmlns:aop="http://www.springframework.org/schema/aop",xsi:schemaLocation中需要加入:http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd)

原理

<aop:aspectj-autoproxy>标签的解析
在前文《Spring源码阅读----Spring IoC之BeanFactory、ApplicationContext》中我们介绍过parseBeanDefinitions方法中,会解析自定义标签

    //xml解析过程中,调用了自定义标签解析
    delegate.parseCustomElement(ele);

    //在BeanDefinitionParserDelegate类中执行
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        // 注释1 找到命名空间
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        // 注释2 根据命名空间找到对应的 NamespaceHandler
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        // 注释3 调用自定义的 NamespaceHandler 进行解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
    }

会根据配置中的标签命名空间 获取 对应的NamespaceHandler,这里关注一下<aop:aspectj-autoproxy>标签,它的handler是org.springframework.aop.config包下的AopNamespaceHandler:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.
     */
    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        // 注释 自定义注解,注册解析器,元素名是 aspectj-autoproxy
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

AspectJAutoProxyBeanDefinitionParser类中关注parse方法:

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // aop 注解的解析入口,注册 AnnotationAwareAspectJAutoProxyCreator
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        // 对注解中子类的处理
        extendBeanDefinition(element, parserContext);
        return null;
    }

继续看看AopNamespaceUtils类中的registerAspectJAnnotationAutoProxyCreatorIfNecessary如何执行的:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        // 通过工具类,注册或升级 AspectJAnnotationAutoProxyCreator
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        // 处理 proxy-target-class 以及 expose-proxy 属性
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);

        // 注册AnnotationAwareAutoProxyCreator组件并通知,让监听器进行处理
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
        if (sourceElement != null) {
            // 解析下面两个属性,如果是 true,将它们加入代理注册器的属性列表中
            // definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE)
            boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
            if (proxyTargetClass) {
                // 处理  proxy-target-class 属性
                // 与代码生成方式有关,在之后步骤中决定使用 jdk 动态代理 或 cglib
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
            if (exposeProxy) {
                // 处理 expose-proxy 属性
                // 扩展增强,有时候目标对象内部的自我调用无法实施切面中的增强,通过这个属性可以同时对两个方法进行增强
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

    private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
        if (beanDefinition != null) {
            // 注册 的beanName 是 org.springframework.aop.config.internalAutoProxyCreator
            parserContext.registerComponent(
                    new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
        }
    }

所以以上,就是注册AnnotationAwareAutoProxyCreator的过程。aop中创建代理对象是通过AnnotationAwareAutoProxyCreator来实现的。

AnnotationAwareAutoProxyCreator

先来看看AnnotationAwareAutoProxyCreator的类图,如下:

AnnotationAwareAutoProxyCreator

可以看到它的父类AbstractAutoProxyCreator实现了BeanPostProcessor接口的子接口InstantiationAwareBeanPostProcessor,这里关注AbstractAutoProxyCreator执行的postProcessBeforeInstantiation方法和postProcessAfterInitialization方法。

postProcessBeforeInstantiation方法

@Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 切面 bean 实例化之前执行的方法
        // 根据beanClass和beanName获取缓存的key
        Object cacheKey = getCacheKey(beanClass, beanName);

        // beanName 不存在 || 目标堆中不存在这个 bean
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // 内层判断是否需要进行切面增强,这是个短路操作,判断成功后将跳过后面的操作
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            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.
        // 如果我们有自定义 TargetSource,请在此处创建代理。
        // 禁止目标bean的不必要的默认实例化:
        // TargetSource将以自定义方式处理目标实例
        //TargetSource实例相当于就是目标对象bean的封装实例
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }

            // 获取当前bean所有的增强数组
            // 实际上委派给子类去实现 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 根据增强数组为目标对象创建代理对象
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());

            //返回代理bean
            return proxy;
        }

        return null;
    }


postProcessAfterInitialization方法

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // 组装 key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 如果适合被代理,则需要封装指定的 bean
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

wrapIfNecessary方法源码:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 如果已经处理过,直接返回
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 不需增强,直接返回
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }

        // 给定的 bean 类是否代表一个基础设施类,基础设置类不应代理
        //或者配置了指定 bean 不需要代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // 如果存在增强方法则创建代理
        //获取当前bean所有的增强数组,也就是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;
    }

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);

        // 决定对于给定 bean 是否应该使用 targetClass 而不是他的接口代理
        if (!proxyFactory.isProxyTargetClass()) {
            // 检查 proxyTargetClass 设置以及 preserveTargetClass 属性
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // 添加代理接口
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // 设置代理工厂属性,将增强数组advisors和目标对象targetSource加入到代理工厂中
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);

        // 自定义定制代理
        customizeProxyFactory(proxyFactory);

        // 用来控制代理工厂被配置之后,是否含允许修改通知
        // 缺省值为 false,不允许修改代理的配置
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        // 调用代理工厂类的getProxy方法创建代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }

通过代码执行过程,我们可以发现是委托给ProxyFactory来创建代理对象的。
ProxyFactory的getProxy方法源码:

    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

    //创建AopProxy对象
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

先是createAopProxy创建AopProxy对象 ,然后通过getProxy获取代理对象
那先来看DefaultAopProxyFactory类中的createAopProxy方法:

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

        // 创建代理
        //这里有两种代理类型 1. JDK 动态代理 2. CGLIB 动态代理
        // isOptimize 判断是否采用优化策略
        //isProxyTargetClass: 该属性对于<aop:aspectj-autoproxy/>标签中的proxy-target-class属性的值.表示是否代理目标类本身,而不是目标类的接口
        //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);
        }
    }

如何选择JDK动态代理(JdkDynamicAopProxy )还是CGLIB代理(ObjenesisCglibAopProxy)?

  • 如果目标对象实现了接口,默认情况下会采用JDK动态代理;但是可以通过配置 proxy-target-class属性的值为true强制使用CGLIB代理,则代理的是目标对象的本身
  • 如果目标对象没有实现接口,那么必须采用CGLIB创建代理对象
    JdkDynamicAopProxy 源码:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

     //....前面省略

    //JdkDynamicAopProxy 构造函数,设置配置信息
    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        } else {
            this.advised = config;
        }
    }

    //创建代理对象
    public Object getProxy() {
        return this.getProxy(ClassUtils.getDefaultClassLoader());
    }

    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }

        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

        // Proxy.newProxyInstance 动态代理创建对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    // 这个熟悉不?因为实现了InvocationHandler接口,所以要重新invoke方法
    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            // 处理 equals 方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // Get the interception chain for this method.
            // 获取此方法的拦截链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            // 检查我们是否有任何切面逻辑。如果我们不这样做,我们可以回退直接反射调用目标,并避免创建 MethodInvocation。
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                //通过反射直接调用目标对象的方法
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                // 将拦截器封装在 ReflectiveMethodInvocation,便于使用 proceed 执行拦截器
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                // 执行拦截器链
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

    //....后面省略
}

ObjenesisCglibAopProxy继承于CglibAopProxy类,其代理对象创建在CglibAopProxy类中实现:

    @Override
    public Object getProxy() {

        // 不传ClassLoader 
        return getProxy(null);
    }

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }

        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            // 创建CGLIB  Enhancer对象,并设置Enhancer对象的各种属性
            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));

            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            // 调用createProxyClassAndInstance方法创建代理对象
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        enhancer.setInterceptDuringConstruction(false);
        enhancer.setCallbacks(callbacks);

        //执行Enhancer的create方法创建代理对象
        return (this.constructorArgs != null && this.constructorArgTypes != null ?
                enhancer.create(this.constructorArgTypes, this.constructorArgs) :
                enhancer.create());
    }

CGLIB 是一套强大的高性能的代码生成工具包,底层通过字节码生成技术ASM框架来实现
什么是CGLIB,参考这篇文章《CGLIB动态代理的实现及原理》

从ObjenesisCglibAopProxy创建代理的对象的步骤可以看到:
最终是由Enhancer 对象来创建代理的,传入的Callback数组,可以是实现了MethodInterceptor接口,并重写intercept的拦截器对象。
每次代理对象执行方法,会执行Callback的intercept方法,会通过执行invokeSuper方法来执行目标类的方法。

总结

好了,到这里我们就算完成了对Spring AOP的了解以及原理的分析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容