关于Java的静态代理与动态代理

1.什么是代理模式?

即Proxy Pattern,是Java的23种设计模式之一。是Spring中AOP(面向切面编程)的底层。

官方回答是:对其它对象提供一种代理以控制对这个对象的访问。

通俗易懂的讲:一个专职于做某件事情的方法只去做它本身该做的事情,其余的事情可以交给其他方法去做,也就是在不改变这个方法本身的基础上对这个方法进行增强。

这么讲还是有点抽象。接下来我举一个简单的例子:

        有位同学和他的女友相识在一个美丽的夜晚,从最初的相识,到之后的相知,然后相爱,如今要步入婚姻的殿堂了。这时出现一个问题:总所周知,结婚本身就是一件耗费精力的事情,更不要说筹划婚宴的场景布置之类的种种琐事。这时婚庆公司出现了,(理想情况下:)他们的专业团队可以帮这位同学解决他的烦恼,也就是代理二位新人去做一些事情,让二位新人只专注于结婚本身。

上述例子中出现了四类角色:

        抽象角色:结婚这件事情(抽象的方法或接口)

        实现角色:实现结婚这件事情(具体的实现方法)

        代理角色:布置婚宴的婚庆公司(对方法进行增强)

        客户角色:委托婚庆中心的新人(通过代理调用实现的方法)

2.代理模式的优势

        1.可以让方法更纯粹,不再关注自身之外的公共业务。

        2.职责分明,减少代码的冗余。

        3.方便于公共业务的管理。

3.静态代理实现

        1.抽象角色:

/**
 * 服务接口
 */
public interface Service {
    void insert();
    void delete();
    void update();
    void select();
}

        2.实现角色:

/**
 * 服务实现类
 */
public class ServiceImpl implements Service{
    @Override
    public void insert() {
        System.out.println("insert");
    }

    @Override
    public void delete() {
        System.out.println("delete");

    }

    @Override
    public void update() {
        System.out.println("update");

    }

    @Override
    public void select() {
        System.out.println("select");

    }
}

        3.代理角色:

/**
 * 服务代理类
 */
public class Proxy {
    private Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public void insert() {
        System.out.println("insert run");
        service.insert();
    }

    public void delete() {
        System.out.println("delete run");
        service.delete();
    }

    public void update() {
        System.out.println("update run");
        service.update();

    }

    public void select() {
        System.out.println("select run");
        service.select();
    }
}

        4.客户角色:

    /**
     * 使用静态代理
     */
    @Test
    public void demo02(){
        Service service = new ServiceImpl();
        Proxy proxy = new Proxy();
        proxy.setService(service);
        proxy.insert();
        proxy.delete();
        proxy.update();
        proxy.select();
    }

        运行结果:

        细心的同学可能就会发现:

                每使用一次代理我们都要写一个对应的代理类,工作量加大辣!开发效率变低辣!

        如何解决?

                接着往下看!

3.动态代理

        所谓动态代理即是通过一些手段动态生成我们的代理类,我们再也不必投入大量的精力去编写代理类辣!

        首先我们要清楚的是:动态代理的底层使用的是Java的反射机制。

        实现动态代理,需要用到Java jdk提供的两个API:Proxy类和InvocationHandler接口。

以下是对动态代理的实现。

        1.动态代理处理器:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理处理器
 * 1.实现InvocationHandler接口
 * 2.实现接口invoke方法
 * 3.生成代理对象
 * 4.编写invoke方法代码
 */
public class ProxyInvocationHandler implements InvocationHandler {
    /**
     * 被代理的接口对象
     */
    private Object object;

    /**
     * 提供set方法
     * @param object
     */
    public void setObject(Object object) {
        this.object = object;
    }

    /**
     * 生成代理对象
     * @return
     */
    public Object getProxy(){
        /**
         * this.getClass().getClassLoader() 获取类反射对象
         * object.getClass().getInterfaces() 获取 被代理的接口 的接口
         * this 当前类
         */
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);

    }
    /**
     * 处理代理示例,并返回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在原方法前增强:
        System.err.println("我要增强你!");

        //执行被代理的接口的方法
        Object invoke = method.invoke(object, args);

        //在原方法后增强:
        System.err.println("我增强完辣!");

        //最后记得返回!
        return invoke;
    }
}

        2.动态代理处理器的使用:

    /**
     * 使用动态代理
     */
    @Test
    public void demo03(){
        //1.创建要动态代理的对象
        Service service = new ServiceImpl();

        //2.创建动态代理处理器对象
        ProxyInvocationHandler handler = new ProxyInvocationHandler();

        //3.通过set方法将要增强的对象注入
        handler.setObject(service);

        //4.调用getProxy获取动态代理对象
        Service proxy = (Service) handler.getProxy();

        //5.通过代理对象调接口方法
        proxy.select();
    }

        运行结果:

        以上是鄙人对Java代理模式的一些理解,应用,和简单封装。希望能对大家有所帮助。如有错误,还望诸位大佬及时指正!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值