Spring AOP实现基础动态代理(Proxy)

本文介绍了Spring AOP中JDK动态代理的实现原理,通过创建InvocationHandler并结合Proxy.newProxyInstance方法生成代理实例。代理类在内存中动态生成,实现了与被代理类相同的接口,以此实现对原有业务逻辑的增强,例如日志记录和安全检查。这种动态代理机制有助于模块解耦和在不修改源代码的情况下添加新功能。
摘要由CSDN通过智能技术生成
 1.JDK中实现动态代理的两个关键类:Proxy(Class)和InvocationHandler(Interface)
 2. Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。 InvocationHandler 是代理实例的 调用处理程序 实现的接口。每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

eg:
代理接口(UserDao):
/**
 * 要代理的接口
 * @author Administrator
 *
 */
public interface UserDao {

     void add();
}

实现代理接口的业务逻辑类(UserDaoImpl):
/**
 * 业务逻辑类
 * @author Administrator
 *
 */
public class UserDaoImpl implements UserDao{

    public void add(){
        System.out.println("save user");
    }
}

要织入的其他类(比如:日志、安全等)(LogInterceptor):
/**
 * 要织入的现有业务逻辑类的类
 * @author Administrator
 *
 */
public class LogInterceptor {

    public  void before(){
        System.out.println("before method");
    }
   
    public  void after(){
        System.out.println("after method");
    }
}

代理实例关联的调用处理程序(MyInvocationHandler(必须实现 InvocationHandler接口,源码中也可以看到)):
/**
 * 调用处理程序
 * @author Administrator
 *
 */
public class MyInvocationHandler implements InvocationHandler {

    private Object target;
   
   
    public MyInvocationHandler(Object target){
        this.target = target;
    }
   
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        LogInterceptor li = new LogInterceptor();
        li.before();  //业务逻辑方法之前调用
        Object obj = method.invoke(target, args);
        li.after();//业务逻辑方法之后调用
        return obj;
    }

}

测试主类:
public class ProxyTest {

    public static void main(String[] args) {
       
        UserDaoImpl target = new UserDaoImpl();
        MyInvocationHandler handler = new MyInvocationHandler(target);
        UserDao proxy = (UserDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{UserDao.class},handler);
        proxy.add();
    }
}


UserDao proxy = (UserDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{UserDao.class},handler);

代理类必须和被代理类实现相同的接口,代理类关联的有调用处理程序,也就是上面的handler对象;而handler对象保存的有实际业务逻辑的引用(构造器传参),所以,我们可以在调用处理程序(handler对象)中实现业务逻辑和其它非业务逻辑等模块的编织。从而实现,我们不用修改现有的实际业务逻辑源代码,也可以实现增加日志、安全等功能,即所谓的AOP(面向切面编程)。 AOP并不是面向对象的代替,而是补充。他们之间的互补,给我们编程又增加了许多简洁、乐趣。

    这里的代理类并不是真正的物理资源,而只是内存中的二进制代码,这也是成为动态代理的原因吧--代理类是在内存中动态生成的。上面的三个参数都是必须的。 1. loader - 定义代理类的类加载器 2. interfaces - 代理类要实现的接口列表,也是Class[]类型的数组。3.指派方法调用的调用处理程序。代码运行时,会先在内存中产生代理类$Proxy.,而代理类的类型是第二个参数来决定的。基于硬性上的要求,我们的代理类必须实现和被代理类相同的接口,也就是这里的UserDao,所以在这里,我把UserDao的class作为数组的元素,在使用反射创建代理对象时,代理对象会自动实现第二个参数数组中的接口。所以,我们可以强制类型转换(向上转型)为UserDao,,调用UsrDao接口中的方法。当我们调用UserDao中的add方法时,代理对象会去调用调用处理程序中的invoke方法,invoke方法中的三个参数说明如下:
1.proxy - 在其上调用方法的代理实例
2.method - 对应于在代理实例上调用的接口方法的 Method 实例。 Method 对象的声明类将是在其中声明方法的接口,该接口可以是  代理类赖以继承方法的代理接口的超接口。
3.args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integerjava.lang.Boolean)的实例中。

以下是JDK API1.6中对代理类的介绍:

动态代理类 (以下简称为 代理类 )是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的 调用处理程序 对象,它可以实现接口 InvocationHandler 。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

使用动态代理的优点:
1.模块解耦
2.源代码不能修改时增加功能
3.提高组件可重用
。。。
算了,有兴趣自己查AOP的优点吧,懒得说啦!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值