Java代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

静态代理

实现同一个接口

public interface Emp {
    public void  work();
}

代理对象

public class Coder implements Emp {
    public void work() {
        System.out.println("Coder 码代码。。。");
    }
}

代理类

public class Manager implements Emp {
    private Coder coder;
    public Manager(Coder coder) {
        this.coder = coder;
    }
    public void work() {
        System.out.println("Manager布置任务。。。");
        coder.work();
        System.out.println("Manager。。。");
    }
}

测试:

public class Main {
    public static void main(String[] args) {
    	//传入代理对象
        Emp manager=new Manager(new Coder());
        manager.work();
    }
}

结果

Manager布置任务。。。
Coder 码代码。。。
Manager。。。

jdk动态代理

准备一个产生代理的工厂类


public class ProxyFactory {
    // 被代理的目标对象
    private Object target;
    // 通过构造方法对目标对象进行初始化
    public ProxyFactory(Object target){
        this.target = target;
    }
    // 申明一个获取对象的方法
    public Object getProxyInstance(){
        //通过JDK提供的Proxy类的静态方法获取一个代理对象
        //参数1:classLoader 目标对象的类加载器
        //参数2:interfaces 目标对象所实现的所有的接口的类型数组
        //参数3:InvocationHandler 调用处理器
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new MyInvocationHandler()
                );
    }

    // 自定义一个InvocationHandler类
    class MyInvocationHandler implements InvocationHandler{

        /**
         *
         * @param proxy  代理对象
         * @param method 被增强的方法对象
         * @param args 被增强的方法的参数对象
         * @return 被增强的方法执行的返回值
         * @throws Throwable
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object returnValue = null;
            //增强处理
            System.out.println("动态代理的前置增强处理...给程序员安排任务");
            // 调用真实的方法
            returnValue = method.invoke(target,args);
            System.out.println("动态代理的前后置强处理...检查程序的任务进度");
            return returnValue;
        }
    }
}

测试:


public class Test {
    public static void main(String[] args) {
        Emp emp = new Coder();
        Emp obj = (Emp) new ProxyFactory(emp).getProxyInstance();
        obj.work();
    }
}

JDK实现的动态代理是基于接口的。JDK动态的生成了一个代理类,这个代理类和目标类实现了同样的接口。就好像我们前面的静态代理一样,Manager和Coder实现了同样的接口,最后我们是按照接口中的API调用代理对象的。

那么这里就会有一个问题,如果我们在Coder中扩展了方法, 则Coder扩展的方法是无法被代理的。

JDK实现的动态代理只能代理接口中定义的方法。

CGLib实现的动态代理

/**
 * @author 戴着假发的程序
 */
public class CGLibProxyFactory {
    // 不需要具体的对象,只要传入对应的class即可。
    // 返回代理对象的
    public Object getObject(Class clazz){
        // 准备一个增强处理器
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(clazz);
        // 设置回调处理器
        enhancer.setCallback(new MethodInterceptor() {
            //参数1:反射生成的目标对象
            // 参数2:目标方法
            // 参数3:方法的参数列表
            // 参数4:代理方法对象
            public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object returnValue = null;
                //增强处理
                System.out.println("动态代理的前置增强处理...给程序员安排任务");
                // 调用真实的方法
                returnValue = methodProxy.invokeSuper(target,args);
                System.out.println("动态代理的前后置强处理...检查程序的任务进度");
                return returnValue;
            }
        });
        //生成代理对象,并且返回
        return enhancer.create();
    }
}

测试:


public class Test {
    public static void main(String[] args) {
//        Emp emp = (Emp) new CGLibProxyFactory().getObject(Coder.class);
//        emp.work();

        Coder coder = (Coder) new CGLibProxyFactory().getObject(Coder.class);
        coder.work();
        coder.tocao();
    }
}

CGLib的动态代理的实现是基于继承的。

CGLib会动态的给代理目标类实现一个子类,并且重写代理目标类的所有方法,进行动态增强。

所以,目标类是否有接口根本就无所谓。

面试题:为什么CGLib实现的动态代理的目标对象可以有接口,也可以没接口?

因为CGLib是基于继承实现的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值