Java的代理模式

        代理,是一种设计模式,提供了对目标对象的一种访问方式,即通过代理访问目标对象。

        代理,从实现方式来分,可以分为两大类:静态代理和动态代理。动态代理根据实现的方式,可以分为:jdk动态实现和cglib动态实现。

一、静态代理

        实现一个对象的静态代理,需要该对象继承一个接口,同时代理类也继承该接口。主要包括三个部分组成:

  • 代理目标接口:代理类和目标实现类的基本模板,代理类和目标类都需要实现接口方法。
  • 目标对象:实现代理目标接口的实现类。
  • 代理类:持有目标对象,根据不同策略选择不同的方法调用目标对象的方法。

        优缺点:

        优点:做到不修改目标对象功能代码的前提下,对目标功能进行扩展,这也是代理模式的最终目的。

        缺点:因为代理类和目标类实现同样的接口,如果修改接口,很多代理类和实现类都要维护,不解耦。

        下面写个简单的静态代理类的实现

        代理目标接口:

public interface Person {

    void say();
}

        两个实现类:Doctor和Police

public class Doctor implements Person{
    @Override
    public void say() {
        System.out.println("my job is Doctor!");
    }
}


public class Police implements Person{
    @Override
    public void say() {
        System.out.println("my job is police!");
    }
}

        代理类,没有修改实现类Person和Doctor任何代码,实现了新增功能,比如打印事件戳。

public class PersonProxy implements Person{

    Person police = new Police();

    Person doctor = new Doctor();

    @Override
    public void say() {

    }

    public void whoSay(String jobName){

        System.out.println(System.currentTimeMillis());

        if (jobName.equals("police")){
            police.say();
        } else if (jobName.equals("doctor")){
            doctor.say();
        } else {
            System.out.println("输入的职业名称暂未录入系统!");
        }
    }

    public static void main(String[] args){
        PersonProxy proxy = new PersonProxy();
        proxy.whoSay("doctor");
        proxy.whoSay("mabi");
    }
}

二、JDK动态代理

        JDK主要使用Java.lang.reflect包中的反射逻辑来实现类的动态代理生成。可根据具体的实现类,动态生成代理。

        由一下四个部分组成:

  • 目标类接口
  • 目标实现类
  • Java.lang.reflect.Proxy类的Object new ProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h),生成动态代理。
  • InvocationHandler接口的实现类:实现调用目标类的扩展逻辑。

        优缺点:

        优点:代理通用的有点,不改变实现类,扩展了功能。

        缺点:必须实现接口,不然无法实现动态代理。

        实现代码样例

        代理目标接口

public interface Person {

    void say(String word);
}

        两个实现类,Doctor和Police

public class Doctor implements Person{
    @Override
    public void say(String word) {
        System.out.println("我是医生,"+word);
    }
}


public class Police implements Person{
    @Override
    public void say(String word) {
        System.out.println("我是警察,"+word);
    }
}

        InvocationHandler接口的实现类,即代理新增功能处理类

public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public ProxyInvocationHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(System.currentTimeMillis());

        Object resultValue = method.invoke(target,args);

        System.out.println("finish: "+System.currentTimeMillis());

        return resultValue;
    }
}

        main方法测试代理调用

public class MyTest {

    public static void main(String[] args){

        Person doctor = new Doctor();

        Person police = new Police();

        //doctor代理处理逻辑
        InvocationHandler doctorHandler = new ProxyInvocationHandler(doctor);

        //police代理处理逻辑
        InvocationHandler policeHandler = new ProxyInvocationHandler(police);

        //生成doctor代理
        Person doctorProxy = (Person) Proxy.newProxyInstance(doctor.getClass().getClassLoader(), doctor.getClass().getInterfaces(),doctorHandler);

        //生成police代理
        Person policeProxy = (Person) Proxy.newProxyInstance(police.getClass().getClassLoader(), police.getClass().getInterfaces(),policeHandler);

        doctorProxy.say("为人民服务");

        policeProxy.say("为人民服务");
    }
}

三、Cglib实现代理

        Cglib不需要实现类有统一的接口,实现方式其实和jdk的动态代理类似,可以理解cglib方式生成的是目标类的子类,通过子类来增强了目标类的功能。

需要以下三个部分:

  • 目标实现类:具体逻辑
  • 代理类:实现MethodInterceptor接口,是代理新增功能的实现
  • Enhancer:设置代理类,并生成代理对象

        实现样例代码:

public class MyDemo {

    public static void main(String[] args){
        LinkManDao linkManDao = new LinkManDao();

        //创建cglib核心对象
        Enhancer enhancer = new Enhancer();

        //设置父类
        enhancer.setSuperclass(linkManDao.getClass());

        //设置回调
        enhancer.setCallback(new MethodInterceptor() {

            /**
             * 当调用目标对象方法时,实际时调用该方法
             *
             * @param proxy:代理对象
             * @param method:目标方法
             * @param args:目标方法的入参
             * @param methodProxy:代理方法
             * @return
             * @throws Throwable
             */

            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("开始存储联系人");
                Object result = method.invoke(linkManDao,args);
                System.out.println("存储联系人结束");
                return result;
            }
        });

        //创建代理对象
        LinkManDao proxy = (LinkManDao) enhancer.create();

        proxy.save();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值