Java进阶:动态代理

动态代理

概念

动态代理:在运行时,动态的创建一组指定的接口的实现类对象。它的作用和装饰者模式比较相似,但是比装饰者模式要灵活:装饰者模式:增强目标固定,增强内容可变;动态代理:增强目标可变,增强内容可变。

使用方法

在Java中使用动态代理,主要是学习InvocationHandler接口和Proxy类的使用

动态代理实例获取方法

Object proxyObject = Proxy.newProxyInstance(
ClassLoader classLoader,
Class[] interfaces,
InvocationHandler handler);

  • 方法作用:动态创建实现了interfaces数组中所有指定接口的实现类对象!
  • 参数:
    (1)ClassLoader:类加载器。它是用来加载器的,把.class文件加载到内存,形成Class对象。
    (2)Class[] interfaces:指定要实现的接口们
    (3)InvocationHandler:代理对象的所有方法(个别不执行,getClass())都会调用InvocationHandler的invoke()方法。

InvocationHandler参数

InvocationHandler是一个抽象类,需要重写。其中有一个抽象方法
public Object invoke(Object proxy, Method method, Object[] args);
这个方法会在调用代理对象所实现接口中的方法时调用。
参数:
目标对象:被增强的对象
代理对象:需要目标对象,然后在目标对象上添加了增强后的对象!
目标方法:增强的内容

实例代码

public class test {

    @Test
    public void fun(){

        /**
         * 动态代理:Proxy#newProxyInstance()
         * 该方法三个参数:
         * ClassLoader 类加载器
         * Class[] interfaces 接口类数组
         * InvocationHandler 代理类中的所有方法都会调用其的invoke方法(个别函数不调用 getClass())
         */

        //得到当前类的类加载器
        ClassLoader loader=this.getClass().getClassLoader();

        InvocationHandler handler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("你好,动态代理!");
                return null;
            }
        };

        //得到Proxy实例
        Object o=Proxy.newProxyInstance(loader,new Class[]{A.class,B.class},handler);

        A a= (A) o;
        B b= (B) o;

        a.a();
        a.aa();
        b.b();
        o.getClass();

    }
}
interface A{
    void a();
    void aa(String s,int i);
}

interface B{
    void b();
}

输出结果:

你好,动态代理!
你好,动态代理!
你好,动态代理!

对于实例代码中的得到的动态代理对象Object o可以强转成 接口A或接口B 即成功创建了该组接口类对象。
这里盗用崔凡希老师的图来说明目标对象调用的方法与InvocationHandler之间的关系
在这里插入图片描述

案例1:增强目标对象

接口Wainter.java

public interface Waiter {

    void service();
}

实现类ManWaiter.java

public class ManWaiter implements Waiter{

    public void service() {
        System.out.println("服务中……");
    }
}

测试类test.java

public class test {
    @Test
    public void Fun(){

        ManWaiter waiter=new ManWaiter();
        //得到本类的类加载器
        ClassLoader loader=this.getClass().getClassLoader();
        //得到InvocationHandler重写类WaiterInvocationHander
        InvocationHandler handler=new WaiterInvocationHander(waiter);

        //得到动态代理
        Waiter waiterProxy= (Waiter) Proxy.newProxyInstance(loader,new Class[]{Waiter.class},handler);
        //动态代理对象调用增强方法
        waiterProxy.service();
    }
}


/**
 * 重写InvocationHandler
 */
class WaiterInvocationHander implements InvocationHandler{
    //底层依赖对象
    private Waiter waiter;

    //构造器
    public WaiterInvocationHander(Waiter waiter){
        this.waiter=waiter;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //前置增强
        System.out.println("您好!");
        waiter.service();
        //后置增强
        System.out.println("再见!");
        return null;
    }
}

案例中传递的增强对象可以改变,但是增强方法使固定的。

案例2:封装成工厂

在案例1的基础上,进一步优化动态代理
前置增强接口AfterAdvice.java

public interface AfterAdvice {
    void after();
}

后置增强接口BeforeAdvice.java

public interface BeforeAdvice {
    void before();
}

代理工厂ProxyFactory.java

public class ProxyFactory {

    private Object targetObject;//目标对象
    private BeforeAdvice beforeAdvice;//前置增强
    private AfterAdvice afterAdvice;//后置增强

    public Object createProxy(){
        //三大参数

        ClassLoader loader=this.getClass().getClassLoader();
        InvocationHandler handler=new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //执行前置增强
                if (beforeAdvice != null) {
                    beforeAdvice.before();
                }

                //执行目标对象的目标函数
                Object result=method.invoke(targetObject,args);

                //执行后置增强
                if (afterAdvice != null) {
                    afterAdvice.after();
                }

                //返回目标函数的返回值
                return result;
            }
        };

        //得到目标对象的实现接口数组
        Class[] interfaces=targetObject.getClass().getInterfaces();
        //得到动态代理
        Object proxy= Proxy.newProxyInstance(loader,interfaces,handler);

        return proxy;
    }

    public Object getTargetObject() {
        return targetObject;
    }

    public void setTargetObject(Object targetObject) {
        this.targetObject = targetObject;
    }

    public BeforeAdvice getBeforeAdvice() {
        return beforeAdvice;
    }

    public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
        this.beforeAdvice = beforeAdvice;
    }

    public AfterAdvice getAfterAdvice() {
        return afterAdvice;
    }

    public void setAfterAdvice(AfterAdvice afterAdvice) {
        this.afterAdvice = afterAdvice;
    }
}

测试类

public class test {
    @Test
    public void fun(){

        //创建工厂
        ProxyFactory factory=new ProxyFactory();

        //设置目标对象
        factory.setTargetObject(new ManWaiter());

        //设置前置增强
        factory.setAfterAdvice(new AfterAdvice() {

            public void after() {
                System.out.println("您好!");
            }
        });

        //设置后置增强
        factory.setBeforeAdvice(new BeforeAdvice() {

            public void before() {
                System.out.println("再见!");
            }
        });

        //得到动态代理
        Waiter waiter= (Waiter) factory.createProxy();

        waiter.service();
    }

}

本例中,通过前置和后置接口的方式,可以实现增强方法的可变性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值