JavaWeb学习笔记之动态代理

本文详细介绍了面向切面编程(AOP)的核心概念之一——代理,并深入探讨了静态代理与动态代理的区别。通过实例展示了如何利用Java的动态代理机制创建代理对象,以及如何结合代理工厂模式来增强目标对象的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理是实现AOP(Aspect oriented program,面向切面编程)的核心和关键技术。

1.什么是代理(proxy)?

代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理。为了保持行为的一致性,代理类和委托类通常会实现相同的接口

  • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,也就是说在程序运行前代理类的.class文件就已经存在。
  • 动态代理:在程序运行时运用反射机制动态创建生成。

这里写图片描述

紫色线代表继承关系,红色线代表调用关系

2. 动态代理

  • JVM可以在运行期动态生成类的字节码,该类往往被用作动态代理类。
  • JVM生成的动态类必须实现一个或多个接口,所以这种只能用作具有相同接口的目标类的代理。
  • CGLIB库可以动态生成一个类的子类,一个类的子类也可作为该类的代理,这个可用来为没有实现接口的类生成动态代理类。
  • 代理类可在调用目标方法之前、之后、前后、以及处理目标方法异常的catch块中添加系统功能代码。

3. 创建代理对象

创建代理对象的作用:动态地生成一个类,该类实现了A,B接口,然后创建该类的对象。
需要创建出一个新类,被ClassLoader加载进方法区。

Proxy.newProxyInstance()方法的三大参数:
1. ClassLoad:
2. Class[] interfaces:需要实现的接口们
3. InvocationHandler: 每次调用都会执行invoke()方法内的代码

//参数一
        ClassLoader loader=this.getClass().getClassLoader();

        //参数二
        Class[] interfaces={A.class,B.class};

        //参数三
        InvocationHandler invocationHandler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("invocation");
                return null;
            }
        };

        //创建一个实现了A接口和B接口的代理对象
        Object proxy= Proxy.newProxyInstance(loader,interfaces,invocationHandler);

        //强转
        A a=(A)proxy;
        B b=(B)proxy;
        System.out.println(proxy.getClass().getName());

InvocationHandler接口只有一个invoke方法,每次调用代理类的方法,即调用了InvocationHandler对象的invoke方法

invoke方法涉及三个要素:

  • 代理对象
  • 代理对象调用的方法
  • 方法接受的参数
    注:Object类的hashCode,equals,toString方法交给invoke,其他的Object类的方法,Proxy有自己的实现。
    调用处理器工作原理

4.实现一个代理工厂模式

需求:男服务员实现服务员接口,在进行服务员的所有方法时,都被beforeAdvice和AfterAdvice装饰

/**@author
 * 用来生成代理对象
 * 它需要所有的参数:
 * 1.目标对象
 * 2.增强内容
 *
 * 代理工厂使用过程:
 *
 * 1.创建代理工厂
 * 2.设置三个成员变量:
 *  目标对象
 *  前置增强
 *  后置增强
 * 3.调用getProxy得到代理对象
 *    执行代理对象的方法时:
 *    执行BeforeAdvice的before()
 *    执行目标对象的目标方法
 *    执行AfterAdvice的after()
 */
public class ProxyFactory {
    private Object targetObject;//目标对象
    private BeforeAdvice beforeAdvice;
    private AfterAdvice afterAdvice;

    //用来生成代理对象
    public Object getProxy(){
        //给出创建Proxy对象的三大参数
        ClassLoader classLoader=this.getClass().getClassLoader();
        Class[] interfaces=targetObject.getClass().getInterfaces();
        InvocationHandler h=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用代理对象的方法时会执行这里的内容
                if (beforeAdvice!=null){
                    beforeAdvice.before();
                }
                Object res=method.invoke(targetObject,args);

                if (afterAdvice!=null)
                    afterAdvice.after();

                return res;

            }
        };
        Object proxyObject= Proxy.newProxyInstance(classLoader,interfaces,h);
        return proxyObject;
    }

    public Object getTargetObject() {
        return targetObject;
public interface Waiter {
    public void serve();
    public void washing();
    public void cashing();
}
public class ManWaiter implements Waiter {
    @Override
    public void serve() {
        System.out.println("serving");
    }

    @Override
    public void washing() {
        System.out.println("washing dishes");
    }

    @Override
    public void cashing() {
        System.out.println("cashing money");
    }

}
public interface BeforeAdvice {
    public void before();
}
public interface AfterAdvice {
    public void after();
}

运行:

public class demo {
    public static void main(String[] args) {
        ProxyFactory factory=new ProxyFactory();
        factory.setTargetObject(new ManWaiter());
        factory.setBeforeAdvice(new BeforeAdvice() {
            @Override
            public void before() {
                System.out.println("this is before .........");
            }
        });
        factory.setAfterAdvice(new AfterAdvice() {
            @Override
            public void after() {
                System.out.println("this is after");
            }
        });

        Waiter waiter= (Waiter) factory.getProxy();
        waiter.serve();
        waiter.washing();
        waiter.cashing();
    }
}

输出:

this is before ………
serving
this is after
this is before ………
washing dishes
this is after
this is before ………
cashing money
this is after

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值