Java静态代理与动态代理
1.静态代理(通过接口实现类去代理另一个接口实现类)
- 解释:静态代理就比如租房这个事件,房东是真实对象,中介是代理对象,我是客户,我要去找中介才能租房子(比自己找更方便,还有中介服务)。房东实现租房接口能出租房子,中介实现租房接口也能出租房子,但是房子是房东的,中介只能代理,于是中介只能靠房东(真实对象)实现出租房子,当然中介还可以加上其它自己想要的操作
- 例子:
租房接口:
package com.lxf.demo01;
//租房接口
public interface Rent {
public void rent();
}
房东(真实对象):
package com.lxf.demo01;
//房东对象
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
中介(代理对象)
package com.lxf.demo01;
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
//将真实对象赋给host
public setHost(Host host) {
this.host = host;
}
@Override
public void rent() {
//看房子
seeHouse();
//签合同
singContract();
//出租房子
host.rent();
//收费
fare();
}
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("中介收中介费");
}
//签合同
public void singContract(){
System.out.println("签租赁合同");
}
}
客户(测试实例):
package com.lxf.demo01;
public class Client {
public static void main(String[] args) {
//房东:真实对象
Host host=new Host();
//代理:代理对象
Proxy proxy = new Proxy();
//将真实对象传给代理对象
proxy.setHost(Host host);
//找中介租房(中介在中间捞油水)
proxy.rent();
}
}
2.动态代理
- 解释:再次看租房这个事件,房东是真实对象,中介是代理对象,我是客户,我要去找中介才能租房子。房东实现租房接口能出租房子,此时中介不实现租房接口,建一个生成代理类的类(通过set或者构造函数接收真实对象,生成代理类),生成代理类的类实现InvocationHandler接口,然后将房东丢入生成代理类的类生成中介代理类,这个于是中介代理类就可以出租房子了,当然中介还可以加上其它自己想要的操作
- 例子:
租房接口:
package com.lxf.demo01;
//租房接口
public interface Rent {
public void rent();
}
房东接口:
package com.lxf.demo01;
//房东对象
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
生成代理类的类:
package com.lxf.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//实现代理类生成的类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的真实对象
private Rent rent;
//设置真实对象
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类
public Object getProxy(){
//Proxy.newProxyInstance(ClassLoader loader,Class<?>[] Ingterfaces,InvocationHandler h);
//第一个参数:真实对象的类加载器
//第二个参数:真实对象实现的所有的接口
//第三个参数: 接口,传递一个匿名内部类对象
return Proxy.newProxyInstance(rent.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质:使用反射机制实现!
//实现方法
Object result = method.invoke(rent, args);
return result;
}
}
客户(测试实例):
package com.lxf.demo03;
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//获取代理角色的类
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//将真实角色加入
handler.setRent(host);
//代理角色
Rent proxy = (Rent) handler.getProxy();
//实现方法
proxy.rent();
}
}
3.静态代理与动态代理异同
-
相同处:都是通过代理对象去实现方法,并且都可以加上其它操作。
-
不同处:静态代理是通过代理对象实现类去代理真实对象实现类,而动态代理是通过一个生成代理类的类去生成代理对象,动态代理的好处在于"很灵活"。静态代理的代理对象是一个实际的类,要是真实对象发生改变,代理对象也要改。而动态代理的代理对象通过类产生,而不完全依赖于类,当真实对象发生改变也没事,甚至可以将生成代理类的类改成万能类:
package com.lxf.demo04; import com.lxf.demo03.Rent; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //实现代理类生成的类 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; } //生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()); //动态代理的本质:使用反射机制实现! Object result = method.invoke(target, args); return result; } }
动态代理分类补充:
- 基于接口:jdk动态代理类
- 基于类:cglib动态代理类
- java字节码实现:javassist(用在JBoss服务器上)