Spring AOP 代理实现的两种方式: JDK动态代理 和 Cglib框架动态代理

来源:互联网 发布:太原207所知乎 编辑:程序博客网 时间:2024/05/02 02:18

1.JDK动态代理

JDK API 内置 ---- 通过 Proxy类,为目标对象创建代理 (必须面向接口代理 ),此文中接口为UserDao,实现类为UserDaoImpl.

public class UserDaoImpl implements UserDao {    @Override    public void save() {        System.out.println("保存方法执行");    }}

下面为目标对象target(UserDaoImpl)创建代理的工厂:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JdkProxyFactory{    //被代理的对象    private Object target;        public JdkProxyFactory(Object target) {        this.target = target;    }        /**     * 用于创建target的代理对象     * @return     */    public Object createProxy(){        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {                        @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                //运行增强的方法                System.out.println("方法增强了");                //运行被代理对象的真正方法                return method.invoke(target, args);            }        });    }}
下面为测试类,为UserDaoImpl创建代理对象,对用代理对象执行UserDaoImpl中的方法

public class JdkProxyTest {    @Test    public void testUseProxy(){        //代理之前的对象        UserDao userDao = new UserDaoImpl();        //代理之后的对象        UserDao userDaoProxy = (UserDao) new JdkProxyFactory(userDao).createProxy();        System.out.println(userDaoProxy);        userDaoProxy.save();    }}

缺点: 使用Jdk动态代理,必须要求target目标对象,实现接口 ,如果没有接口,不能使用Jdk动态代理


2.Cglib 动态代理

CGLIB(CodeGeneration Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。

Cglib 不但可以对接口进行代理,也可以对目标类对象,实现代理(解决了 Jdk 只能对接口代理问题 )。在spring3.2版本 core包中内置cglib 类。

下面为ProductDao使用cglib为其创建代理对象

public class ProductDao {        public void saveProdcut(){        System.out.println("产品保存");    }}

创建代理对象的工厂:

import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;/** * 使用cglib进行代理 --- 工厂类 *  */public class CglibProxyFactory implements MethodInterceptor {// 被代理目标对象private Object target;// 在构造工厂时传入被代理对象public CglibProxyFactory(Object target) {this.target = target;}// 创建代理对象方法public Object createProxy() {// 1、 创建Enhancer对象Enhancer enhancer = new Enhancer();// 2、 cglib创建代理,对目标对象,创建子类对象enhancer.setSuperclass(target.getClass());// 3、传入 callback对象,对目标增强enhancer.setCallback(this);return enhancer.create();}@Override/** * proxy 代理对象 * method 当前调用方法 * args 方法参数 * methodProxy 被调用方法代理对象 (作用:执行父类的方法) */public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("记录日志......");// 按照JDK编程// return method.invoke(target, args);return methodProxy.invokeSuper(proxy, args);}}


下面为测试类:

import org.junit.Test;public class CglibProxyTest {    @Test    public void test(){        ProductDao productDao = new ProductDao();        ProductDao productDaoProxy = (ProductDao) new CglibProxyFactory(productDao).createCglibProxy();        productDaoProxy.saveProdcut();    }}

运行结果如下:



Cglib 创建代理思想:对目标类创建子类对象

       设置 superClass 对哪个类创建子类 (类似 JDK代理 接口)

       设置 callback 实现增强代码 (类似 JDK代理InvocationHandler )

 

在cglib的callback函数中,要执行被代理对象的方法

       method.invoke(target,args); 等价于 methodProxy.invokeSuper(proxy,args); 




优先对接口代理(使用JDK代理),如果目标没有接口,才会使用cglib代理



阅读全文
0 0
原创粉丝点击