• 什么是AOP?


      在运行时,动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。AOP即面向切面编程。使用切面编程,可以将一些系统性的代码提取出来,独立实现,与核心业务代码剥离,比如权限管理、事务管理、日志记录等等。AOP是spring提供的关键特性之一。

    AOP的实现原理

      AOP分为静态AOP和动态AOP,静态AOP是由AspectJ实现的AOP,动态AOP是指将切面代码进行动态织入实现的AOP,Spring的AOP为动态AOP。实现的技术为:JDK提供的动态代理技术和CGLIB(动态字节码增强技术)两种。尽管实现技术不一样,但 都是基于代理模式 , 都是生成一个代理对象 。

      JDK动态代理实现:查看我前面的博文-动态代理,我们看到该方式有一个要求, 被代理的对象必须实现接口,而且只有接口中的方法才能被代理 。也就是jdk代理方式是基于接口的一种代理方式。

      CGLIB:字节码生成技术实现AOP,其实就是继承被代理对象,然后Override需要被代理的方法,在覆盖该方法时,自然是可以插入我们自己的代码的。

    因为需要Override被代理对象的方法,所以自然CGLIB技术实现AOP时,就 必须要求需要被代理的方法不能是final方法,因为final方法不能被子类覆盖 。

    我们使用CGLIB实现上面的例子:

    package net.aazj.aop;
    import java.lang.reflect.Method;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    public class CGProxy implements MethodInterceptor{
        private Object target;    // 被代理对象
        public CGProxy(Object target){
            this.target = target;
        }
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
            System.out.println("do sth before....");
            Object result = proxy.invokeSuper(arg0, arg2);
            System.out.println("do sth after....");
            return result;
        }
        public Object getProxyObject() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(this.target.getClass());    // 设置父类
            // 设置回调
            enhancer.setCallback(this);    // 在调用父类方法时,回调 this.intercept()
            // 创建代理对象
            return enhancer.create();
        }
    }
    public class CGProxyTest {
        public static void main(String[] args){
            Object proxyedObject = new UserServiceImpl();    // 被代理的对象
            CGProxy cgProxy = new CGProxy(proxyedObject);
            UserService proxyObject = (UserService) cgProxy.getProxyObject();
            proxyObject.getUser(1);
            proxyObject.addUser(new User());
        }
    }

    观察spring中AOP相关源码可知,如果被代理对象实现了接口,那么就使用JDK的动态代理技术,反之则使用CGLIB来实现AOP,所以 Spring默认是使用JDK的动态代理技术实现AOP的 。

    AOP在spring中的使用

    Spring中AOP的配置一般有两种方法,一种是使用 <aop:config> 标签在xml中进行配置,一种是使用注解以及@Aspect风格的配置。

    1) 基于<aop:config>的AOP配置

    <tx:advice id="transactionAdvice" transaction-manager="transactionManager"?>
        <tx:attributes >
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="append*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="get*" propagation="SUPPORTS" />
            <tx:method name="find*" propagation="SUPPORTS" />
            <tx:method name="load*" propagation="SUPPORTS" />
            <tx:method name="search*" propagation="SUPPORTS" />
            <tx:method name="*" propagation="SUPPORTS" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="transactionPointcut" expression="execution(* net.aazj.service..*Impl.*(..))" />
        <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
    </aop:config>
    <bean id="aspectBean" class="net.aazj.aop.DataSourceInterceptor"/>
    <aop:config>
        <aop:aspect id="dataSourceAspect" ref="aspectBean">
            <aop:pointcut id="dataSourcePoint" expression="execution(public * net.aazj.service..*.getUser(..))" />
            <aop:pointcut expression="" id=""/>
            <aop:before method="before" pointcut-ref="dataSourcePoint"/>
            <aop:after method=""/>
            <aop:around method=""/>
        </aop:aspect>
        <aop:aspect></aop:aspect>
    </aop:config>

    <aop:aspect> 配置一个切面;

    <aop:pointcut>配置一个切点,基于切点表达式;

    <aop:before>,<aop:after>,<aop:around>是定义不同类型的advise. a

    spectBean 是切面的处理bean

    2) 基于注解和@Aspect风格的AOP配置

    参考链接:面试题思考:解释一下什么叫AOP(面向切面编程)

    Spring源码--AOP实现(1)--创建AopProxy代理对象

    Spring源码--AOP实现(2)--拦截器调用的实现

  • 相关阅读:
    正则表达式记录
    XMLHttpRequest(Ajax)不能设置自定义的Referer
    删除右键菜单上的Adobe Drive CS4,Win7上也没有问题
    A HOWTO on Optimizing PHP(如何优化PHP的一篇文章)
    PHP XML To Array,将XML转换为数组
    让图片在高度确定的块元素中垂直居中
    (转)2011年,還是微軟IE的天下~網頁設計師哭泣吧!
    产生类似GUID的唯一ID
    转:编写跨浏览器兼容的 CSS 代码的金科玉律
    array_intersect 比 array_diff 快
  • 原文地址:https://www.cnblogs.com/jxxblogs/p/12142734.html
Copyright © 2020-2023  润新知