Spring AOP原理 浅析

Spring AOP 通过JDK动态代理与Cglib代理2种方式实现,因此在学习Spring AOP实现前,需要先了解代理模式,请参考Java设计模式-代理模式。

Spring AOP 理解

我的理解:aop就是具体方法调用前后做你想做的事情,这样可以避免大量代码重复出现。Spring4.3开发手册AOP介绍中提到“横切“、“方面“等术语,自我感觉好深奥,而且不容易懂;其实当我弄明白代理模式后,再看看Spring AOP的源代码,我觉得忘记那些术语就行了,只要记得 aop在目标对象方法执行前后都可以起作用,但 目标对象方法的执行是独立的就可以。

AOP常用的场景

想必大家都有所了解,比如记录日志,事务处理,列举如下:
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging  调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence  持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务

AOP代理机制

官方文档翻译如下:

Spring AOP 使用JDK动态代理或CGLIB创建目标对象的代理(JDK动态代理是首选)。
如果代理的目标对象实现了接口,那么将使用JDK动态代理,所有目标类实现的接口都将被代理。如果目标类对象没有实现任何接口,就创建CGLIB代理。

具体代码实现 在Spring中由AopProxyFactory根据AdvisedSupport对象的配置来决定使用哪种代理方式生成代理对象。(我用的是Spring 4.3.2)
源代码:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public DefaultAopProxyFactory() {
    }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {       
         //没有配置强制使用Cglib代理,且目标类实现接口,使用jdk动态代理
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

强制使用Cglib代理的配置

XML配置

<aop:config proxy-target-class="true">
    
aop:config>

<aop:aspectj-autoproxy proxy-target-class="true"/>

注解配置

@EnableAspectJAutoProxy(proxyTargetClass = true)

Springboot中引入aop包后,默认开启扫描使用注解@AspectJ的类,如果不强制使用Cglib代理,不需要增加注解@EnableAspectJAutoProxy

Spring AOP 使用示例

这里有比较好的示例,参考Spring Boot中使用AOP统一处理Web请求日志

Spring AOP不支持代理类内部方法调用的拦截

比如类中a方法调用b方法,切面拦截b方法会失败的
解决方法 参考:http://blog.csdn.net/quzishen/article/details/5803721

参考资料:
Spring 开发手册AOP介绍

你可能感兴趣的:(Spring)