Spring--AOP详解

jopen 12年前

        AOPAspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现

Spring--AOP详解

        按自己理解解释一下这个图,

        AOP是将多个方法中都用到的某部分代码封装到SecurityHandler中。要是想把这部分代码插入到需要的地方,首先我们需要知道在哪些点进行插入。每一个具体的方法对应着的为joinpoint,而如果是符合某种正则式的方法集则对应着pointcut。在配置时,是不需要配置joinpoint的,但是如果,你想取得你目前正在调用的是哪个方法,则可以用joinpoint获得。在这里,我们定义我们要针对哪些方法进行操作。插入吗,是在方法实现之前插入还是在之后插入呢?这就涉及到advice(具体分为before adviceafter advicethrow advice)。SecurityHandler中代码注入到具体的方法中的过程则成为weave

       Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象(包括切入点的描述和通知的描述)

        Joinpoint(连接点)所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,

因为spring只支持方法型的连接点,实际上joinpoint还可以是field或者构造器。

       Pointcut(切入点)所谓切入点是指我们要对那些joinpoint进行拦截的定义。

Advice(通知):所谓通知是指拦截到jointpoint之后所要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知。

      Target(目标对象)代理的目标对象

      Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入

      Introducton(引入)在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field

       代码演示:例一采用jpa注解形式

@Aspect

public class SecurityHandler {

    /**

     * 定义PointcutPointcut的名称为addAddMethod(),此方法没有返回值和参数

     * 该方法就是一个标识,不进行调用

     */

    @Pointcut("execution(* add*(..))")

    privatevoidaddAddMethod(){}

    /**

     * 定义Advice,表示我们的Advice应用到哪些Pointcut订阅的Joinpoint

     */

    @Before("addAddMethod()")

    //@After("addAddMethod()")

    privatevoidcheckSecurity() {

        System.out.println("-------checkSecurity-------");

    }      

}

      配置文件需配置:

  <!--启用AspectJAnnotation的支持 -->      

    <aop:aspectj-autoproxy/>       

<bean id="securityHandler"class="com.bjpowernode.spring.SecurityHandler"/>

例二采用配置文件配置形式:

<beanid="securityHandler"class="com.bjpowernode.spring.SecurityHandler"/>

    <aop:config>

        <aop:aspectid="securityAspect"ref="securityHandler">

            <!--

            add开头的方法

            <aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>

             -->

             <!--

             com.bjpowernode.spring包下所有的类所有的方法

            <aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/>

             -->

            <aop:pointcutid="addAddMethod"expression="execution(* com.bjpowernode.spring.*.add*(..)) || execution(* com.bjpowernode.spring.*.del*(..))"/>

            <aop:beforemethod="checkSecurity"pointcut-ref="addAddMethod"/>

        </aop:aspect>

    </aop:config>

       Spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的。

       JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。

      CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。

       下面演示动态代理的实现例三

public class SecurityHandlerimplements InvocationHandler {

    private ObjecttargetObject;

    public Object createProxyInstance(Object targetObject) {

        this.targetObject = targetObject;

        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),

                               targetObject.getClass().getInterfaces(),

                               this);

    }

    public Object invoke(Object proxy, Method method, Object[] args)

        throws Throwable {

        checkSecurity();

        //调用目标方法

        Object ret = method.invoke(targetObject, args);

        return ret;

    }

    privatevoid checkSecurity() {

        System.out.println("-------checkSecurity-------");

    }      

}

客户端实现:

public class Client {

    publicstaticvoid main(String[] args) {

        SecurityHandler hander =new SecurityHandler();

        UserManager useraManager = (UserManager)hander.createProxyInstance(new UserManagerImpl());

        useraManager.addUser("张三","123");

    }

}