Java动态代理

动态代理

1.代理模式

为什么要有代理?生活中有很多这样的例子,比如,你要出去旅游,但是你又不想自己做攻略(要考虑交通、食宿、门票,太麻烦了,又浪费时间),那么就可以找家旅行社报团,它会帮你安排整个行程(带个手机拍照就可以了),这时候旅行社就是代理,你自己就是被代理对象。

代理模式:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者,所以代理模式包含3个角色:被代理角色,代理角色,抽象角色(被代理角色和代理角色都需要遵守的协议)

2.代理模式-静态代理

定义旅行的接口

public interface Travel {
	//旅游方法
    public abstract void travel();
}

定义游客类,实现旅行接口

public class Tourist implements Travel{
	//游客旅行
    public void travel() {
        System.out.println("张三去云南旅游...");
    }
}

定义旅行社类,同样实现旅行接口,并且定义游客属性,通过构造函数初始化属性值

public class TravelAgency implements Travel {
    private Tourist tourist; //定义游客属性

    public TravelAgency(Tourist tourist) {
        this.tourist = tourist;
    }
	//虽然还是游客旅行,但是前后有了旅行社的安排,很方便
    public void travel() {
        System.out.println("旅行社联系旅游巴士...");
        tourist.travel(); //执行游客的旅行方法
        System.out.println("旅行社安排吃饭住宿...");
    }
}

定义测试类

@Test
public void method1() {
     //创建游客对象
     Tourist tourist = new Tourist();
     //创建代理类旅行社对象,并传入游客参数
     TravelAgency travelAgency = new TravelAgency(tourist);
     //1. 不找代理
     tourist.travel();
     //2. 找代理
     travelAgency.travel();
}

运行结果:

张三去云南旅游...
旅行社联系旅游巴士...
张三去云南旅游...
旅行社安排吃饭住宿...

在上面的例子中,分别扮演的角色:

TravelAgency-代理对象

Tourist-被代理类

Travel-抽象角色

所以,静态代理,代理类是真是存在的。

3.代理模式-动态代理

定义:动态代理就是直接通过反射生成一个代理对象,代理对象所属的类是不需要存在的。jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象

先举例:

public static void main(String[] args) {
        final Tourist tourist = new Tourist();
        Travel travel = (Travel) Proxy.newProxyInstance(Tourist.class.getClassLoader(), Tourist.class.getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (method.getName().equals("travel")){
                            System.out.println("旅行社联系旅游巴士...");
                            // 通过反射来调用被代理对象的方法
                            method.invoke(tourist);
                            System.out.println("旅行社安排吃饭住宿...");
                        }
                        return null;
                    }
                });
        travel.travel();
    }

运行结果:

旅行社联系旅游巴士...
张三去云南旅游...
旅行社安排吃饭住宿...


3.1 Proxy类的Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法中参数解析:
  • Tourist.class.getClassLoader():被代理类的类加载器

  • Tourist.class.getInterfaces():被代理类所有实现的接口的Class对象

  • new InvocationHandler() { invoke() }:(接口)执行处理类

  • 返回值: 代理对象

  • 前2个参数是为了帮助在jvm内部生成被代理对象的代理对象,第3个参数,用来监听代理对象调用方法,帮助我们调用方法

3.2 InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法参数解析:
  • proxy:代理对象(慎用)
  • method:当前执行的方法
  • args:当前执行的方法运行时传递过来的参数
  • 返回值:当前方法执行的返回值

所以,动态代理,代理类是不真实存在的,但代理类是一定实现了被代理类的接口的

posted @ 2021-12-27 15:22  时光巷陌  阅读(23)  评论(0编辑  收藏  举报