Rent.java和HouseOwner.java不变,增加Proxys.java,然后测试
在静态代理中,房东HouseOwner是(真实的角色)被代理的角色,而Proxys是代理房东去出售房屋的,所以Proxys是代理对象。可以看出 真实对象和代理对象都实现了Rent接口(出租房子的接口)。并且代理对象中保存了真实对象的引用。
当然也可以这样,Proxys类里保存接口。面向对象的特性,在new Proxys类的对象的时候,可以传入接口的实现类,多态特性,接口指向实现类。
再来一个真实项目中的例子,方便理解静态代理:
也就是说真实对象和代理对象都要实现同一接口,UserService, 和之前租房的例子一样,都要实现Rent接口。然后代理类里保存一线接口的引用或者真实对象的引用,毕竟多态,真实对象也是实现了接口的。
动态代理和静态代理的区别:
静态代理的代理类是开发人员需要手动写,
而动态代理的代理类是动态生成的。
动态代理的分类:
基于接口的代理 : JDK动态代理
基于类的代理 : cglib
在这里需要了解一个类和一个接口:
Proxy类和invocationHandler接口,不知道的可以去文档里查一下这两个。
用动态代理改造租房例子,HouseOwner和 Rent接口不变 ,新增一个类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 本类的作用是动态生成代理
public class MyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Rent rent;
// 构造方法
public MyInvocationHandler(Rent rent) {
this.rent = rent;
}
public Object getProxy(){
return Proxy.newProxyInstance
(rent.getClass().getClassLoader(),
rent.getClass().getInterfaces(),
this);
}
// invoke属于自动调用的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
see();
Object result = method.invoke(rent, args);
charge();
return result;
}
public void see(){
System.out.println("中介带想要租房的人看房");
}
public void charge(){
System.out.println("中介收钱");
}
}
测试类:
public class Test {
public static void main(String[] args) {
HouseOwner houseOwner = new HouseOwner();
MyInvocationHandler handler =
new MyInvocationHandler(houseOwner);
Rent proxy = (Rent) handler.getProxy();
proxy.rent();
}
}
结果:
下来改造成公用的,不能是保存Rent接口了,必须是传什么接口,就替实现了那个接口的真实对象动态生成代理对象;代码如下
然后再改写一下 UserService 采用动态代理,使得执行add和delete方法执行之前和之后,都打印一下执行xxx方法之前和执行xxx方法之后。
如果改一下 Test类的 proxy.delete()
这样的话 ,UserServiceImpl类并没有改动代码,UserService接口的代码也没有变,却增加了业务的功能,可以把这个xxx方法执行之前 和 xxx方法执行之后,做成事务控制和日志,或者做成自己想要的功能都可以。这个就是jdk的动态代理
有些小伙伴会问了,那可不可以代理多个类呢?
当然可以,想一下假如还有个类也是实现了UserService这个接口,那么测试代码还是不变的,因为 UserService userService = new xxx() ,这个xxx实现了UserService接口,接口保存实现类对象,动态代理代理的是实现了接口的那些真实类的对象,多态的运用很奇妙。
其实换个思维来想,设计模式就是把类,抽象类,接口,这些面向对象,面向接口组合起来,如果java基础扎实,那么设计模式必须看得懂。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。