Java动态代理的设计与实现

简述Java代理模式的设计与实现

1.代理对象存在的价值主要用于拦截对真实业务对象的访问,建立代理类是为了增强、扩展被代理类(即目标对象)的功能,实际上业务还是调用目标对象的方法。

2.实现:

第一步:先写一个接口,接口中封装了客户端(目标对象)需要的执行的操作

第二步:代理和客户端同时实现该接口,其中客户端中真正实现了接口中的方法,是一个真正的实体类,而代理只是保存了一个客户端的引用,使得其能访问该实体,代理在实现的接口中通过反射调用实体中的方法

其实代理模式有点像明星与经纪人的关系,明星不用操心接通告接代言的事,这些都交由经纪人打理,但最后演戏拍广告都由明星出演。这个例子中明星就相当于目标对象,经纪人就是代理对象。

动态代理技术

动态代理是一种较为高级的代理模式,动态代理技术主要有JDK,CGLIB,Javasst ,ASM。其中JDK主要针对接口代理,它的典型应用就是Spring AOP。CGLIB针对类进行代理。

静态代理实例

//这里创建了一个接口
public interface Study {
    void math(String math);
    void english(String english);

}

//下面是接口实现类
public class StudyImpl implements Study{
    @Override
    public void math(String math) {
        System.out.println("考试科目为:"+math);
    }

    @Override
    public void english(String english) {
        System.out.println("您正在进行"+english);
    }
}
//这是一个静态代理类
public class staticProxy implements Study{

    Study stu;
    public staticProxy(Study target) {
        this.stu=target;
    }

    public static void main(String[] args) {
        Study st=new StudyImpl();
        staticProxy s=new staticProxy(st);
        s.math("数学");
        s.english("英语");
    }

    @Override
    public void math(String math) {
        System.out.println("考试开始,请在答题纸上做答");
        stu.math("数学");
        System.out.println("考试结束,请放下笔等待收卷");
    }

    @Override
    public void english(String english) {
        System.out.println("考试开始,请在答题纸上做答");
        stu.english("英语");
        System.out.println("考试结束,请放下笔等待收卷");
    }
}
ouput:
考试开始,请在答题纸上做答
考试科目为:数学
考试结束,请放下笔等待收卷
考试开始,请在答题纸上做答
考试科目为英语
考试结束,请放下笔等待收卷

通过实例我们可以看出在静态代理类中实现了增强的方法,而且调用的是实现类的方法

动态代理实例

以下实例为jdk动态代理

//这里动态代理实现的接口和代理类与静态代理相同,创建了一个ProxyHandler类来增强方法
public class ProxyHandler implements InvocationHandler {

    private Object target;
    public ProxyHandler(Object target){
        this.target=target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("考试开始,请在答题纸上做答");
        Object obj= method.invoke(target,args);
        System.out.println("考试结束,请放下笔等待收卷");
        return obj;
    }

//动态代理类
public class proxyTest{

    public static void main(String[] args) {
        Study s=new StudyImpl();
        ProxyHandler p=new ProxyHandler(s);
        Study proxy= (Study) Proxy.newProxyInstance(s.getClass().getClassLoader(),s.getClass().getInterfaces(),p);
        proxy.math("数学");
        System.out.println("代理对象proxy的类型"+proxy.getClass());
        System.out.println("代理对象proxy的父类"+proxy.getClass().getGenericSuperclass());
    }
}
output:
考试开始,请在答题纸上做答
考试科目为:数学
考试结束,请放下笔等待收卷
代理对象proxy的类型class com.sun.proxy.$Proxy0
代理对象proxy的父类class java.lang.reflect.Proxy

总结

  • 由动态代理实例可以看到,com.sun.proxy.$Proxy0 代理对象继承了一个java.lang.reflect.Proxy类并且实现了代理接口。而java语言允许只单继承,接口可以有多个。所以jdk动态代理不能代理类,只能代理接口。
  • 动态代理与静态代理相比,当有多个类需要增强方法时,静态代理会重复写多个代理类,增加工作量。而使用动态代理创建了ProxyHandler,代理类只需将被代理类传入ProxyHandler的构造器中便可增强方法
  • jdk动态代理需要提供接口才能代理,当有些类不方便提供接口时我们就要使用cglib动态代理了,它只要提供一个非抽象类就能进行代理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值