代理模式

本文介绍了Java动态代理的实现,包括JDK动态代理的四个步骤,并提供了示例代码。对于没有接口的类,文章讲解了CGLib的使用,包括两种不同的实现方式。CGLib通过字节码技术创建子类来实现动态代理,适用于非接口类的代理。这些内容是SpringAOP的基础。
摘要由CSDN通过智能技术生成

简介

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

JDK动态代理

代理步骤:

    (1)定义一个事件管理器类实现invocationHandle接口,并重写invoke(代理类,被代理的方法,方法的参数列表)方法。 
    (2)实现被代理类及其实现的接口
    (3)调用Proxy.newProxyInstance(类加载器,类实现的接口,事务处理器对象);生成一个代理实例。 
    (4)通过该代理实例调用方法。

代码实现:

JDK动态代理,为接口实现的对象创建代理。具体详见源码

//1. 抽象主题  
public interface Moveable {  
    void move()  throws Exception;  
}  
//2. 真实主题  
public class Car implements Moveable {  
    public void move() throws Exception {  
        Thread.sleep(new Random().nextInt(1000));  
        System.out.println("汽车行驶中…");  
    }  
}  
//3.事务处理器  
public class TimeHandler implements InvocationHandler {  
    private Object target;  
    
    // 实现代理类
    public TimeHandler(Object target) {  
        super();  
        this.target = target;  
    }  
   
    /** 
     * 参数: 
     *proxy 被代理的对象 
     *method 被代理对象的方法 
     *args 方法的参数  
     *Object 方法返回值 
     */  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        long startTime = System.currentTimeMillis();  
        System.out.println("汽车开始行驶…");  
        method.invoke(target, args);  
        long stopTime = System.currentTimeMillis();  
        System.out.println("汽车结束行驶…汽车行驶时间:" + (stopTime - startTime) + "毫秒!");  
        return null;  
    }  
   
}  
//测试类  
public class Test {  
    public static void main(String[] args) throws Exception{  
        Car car = new Car();  
        InvocationHandler h = new TimeHandler(car);  
        Class<?> cls = car.getClass();  
        /** 
         *loader 类加载器 
         *interfaces 被代理类实现的接口 
         *h InvocationHandler  事物处理器
         */  
        Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h);  
        m.move();  
    }  
}  

cglib动态代理

针对于非接口实现的对象,创建的是类的代理类,然后由代理类创建对象

写法一:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

//1.具体主题  
public class Train{  
    public void move(){  
        System.out.println("火车行驶中…");  
    }  
}  
//2.生成代理
public class CGLibProxy implements MethodInterceptor {  
    private Enhancer enhancer = new Enhancer();  
    public Object getProxy(Class<?> clazz){  
        enhancer.setSuperclass(clazz);  
        enhancer.setCallback(this);  
        return enhancer.create();  
    }  
    /** 
     * 拦截所有目标类方法的调用 
     * 参数: 
     * obj  目标实例对象 
     * method 目标方法的反射对象 
     * args 方法的参数 
     * proxy 代理类的实例 
     */  
    public Object intercept(Object obj, Method method, Object[] args,  
            MethodProxy proxy) throws Throwable {  
        //代理类调用父类的方法  
        System.out.println("日志开始");  
        proxy.invokeSuper(obj, args);  
        System.out.println("日志结束");  
        return null;  
    }  
}  
//3.测试  
public class Test {  
    public static void main(String[] args) {  
        CGLibProxy proxy = new CGLibProxy();  
        Train t = (Train) proxy.getProxy(Train.class);  
        t.move();  
    }  
}  

写法二:

import java.lang.reflect.Method;
 
import dc.com.dao.CustomerDaoImpl;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
 
public class BeanFactory {
    public static CustomerDaoImpl getBean() {
        // 准备目标类
        final CustomerDaoImpl goodsDao = new CustomerDaoImpl();
        // 创建切面类实例
        final Aspect myAspect = new Aspect();
        // 生成代理类,CGLIB在运行时,生成指定对象的子类,增强
        Enhancer enhancer = new Enhancer();
        // 确定需要增强的类
        enhancer.setSuperclass(goodsDao.getClass());
        // 添加回调函数
        enhancer.setCallback(new MethodInterceptor() {
            // intercept 相当于 jdk invoke,前三个参数与 jdk invoke—致
            @Override
            public Object intercept(Object proxy, Method method, Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                myAspect.myBefore(); // 前增强
                Object obj = method.invoke(goodsDao, args); // 目标方法执行
                // 或者这种写法 Object obj = methodProxy.invokeSuper(proxy, args);
                myAspect.myAfter(); // 后增强
                return obj;
            }
        });
        // 创建代理类
        CustomerDaoImpl goodsDaoProxy = (CustomerDaoImpl) enhancer.create();
        return goodsDaoProxy;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值