切面编程(一)

一、切面编程概述

  Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。

  什么是代理:代理(Proxy)是一种设计模式, 提供了对目标对象另外的访问方式,即通过代理访问目标对象。这样可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)

二、JDK静态代理和动态代理

  JDK代理内容详细见 http://www.cnblogs.com/jiyukai/p/6958744.html

三、cglib代理

    Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。

    (1)JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。

    (2)CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOPdynaop,为他们提供方法的interception(拦截)。 

    (3)CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。   

   Cglib子类代理Demo实现 

  (1) 需要引入cglib系列jar文件,但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-x.x.x.jar即可;

  (2)引入功能包后,就可以在内存中动态构建子类;

  (3)代理的类不能为final修饰;

  (4)如果目标对象的方法为final/static, 那么将不会被拦截。

   具体实现代码

   1.业务实现类,即将被代理的目标对象

package com.jyk.spring.cglib;

public class UserDao {

    public void cglibTest()
    {
        System.out.println("cglib代理执行方法");
    }
}

  2. cglib代理工厂,必须实现MethodInterceptor接口

package com.jyk.spring.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/*
 * cglib子类代理工厂
 * 必须实现MethodInterceptor接口
 * 对UserDao在内存中动态构建一个子类对象
 */
public class UserCglibProxy implements MethodInterceptor{

    //维护目标对象
    private Object target;
    
    public UserCglibProxy(Object target)
    {
        this.target = target;
    }
    
    /*
     * 给目标对象创建代理对象
     */
    public Object getProxyInstance()
    {
        //1、初始化工具类
        Enhancer en = new Enhancer();
        
        //2、设置父类
        en.setSuperclass(target.getClass());
        
        //3、设置回调函数,触发intercept方法
        en.setCallback(this);
        
        //4、创建子类(即代理对象)
        return en.create();
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] arg2,
            MethodProxy proxy) throws Throwable {
        
        System.out.println("执行开始");
        
        //执行目标对象的方法
        Object returnValue = method.invoke(target, arg2);
        
        System.out.println("执行结束");
        return returnValue;
    }

}

  3.执行结果,由打印出来的对象可以看到proxy已经不是原有UserDao,而是经过cglib代理生成的代理对象

  

  结论:在SpringAOP编程中,

  如果加入容器的目标对象有实现接口,用JDK代理;如果目标对象没有实现接口,用Cglib代理;

posted @ 2018-07-29 14:32  纪煜楷  阅读(797)  评论(0编辑  收藏  举报