目录
- 一、静态代理
- 二、动态代理
一、静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
代理接口:
/**
* 代理接口
*/
public interface Rent {
public void rent();
}
委托类,具体处理业务:
/**
* 房东要出租房子
*/
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房东出租房子!");
}
}
静态代理类 :
/**
* 房子中介:代理
*/
public class Proxyhome implements Rent{
private Host host;
public Proxyhome(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
fare();
}
// 看房
public void seeHouse(){
System.out.println("中介带你看房子!");
}
// 收中介费
public void fare(){
System.out.println("中介收中介费!");
}
}
客户类 :
public class Client {
public static void main(String[] args) {
Host host = new Host();
//代理房东买房子
Proxyhome proxy = new Proxyhome(host);
proxy.rent();
}
}
静态代理的优缺点:
优点:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务。
- 公共业务发生扩展的时候,方便集中管理!
缺点:
- 一个真实角色就会产生一个代理角色;代码量会翻倍一开发效率会变低
二、动态代理
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
PS反射可以通过类的类加载器直接获得类的任何信息(许多框架都是建立在反射上的,如Spring系列),也可以参考注解和反射 体验反射的强大功能。
再者动态代理有点类似Spring中AOP(横向切入),在不改变原有的代码上加入需要的业务。
动态代理和静态代理角色一样。动态代理的代理类是动态生成的,不是我们直接写的!
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:JDK动态代理**【我们在这里使用】**
- 基于类:cglibo
- ava字节码实现:javasist
动态代理的实现类:
/**
* 动态代理卖房子业务
*/
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Rent rent;
public void setRent(Rent rent){
this.rent=rent;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.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;
}
}
客户类:
public class Client2 {
public static void main(String[] args) {
Host host = new Host();
//代理房东买房子
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host);
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
}
动态代理的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共也就就交给代理角色!实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
基于接口的动态代理的代码差不多是固定的,我们可以把固定的代码做成一个工具类。下面给出:
/**
* 代理工具类
*/
public class ProxyObjectInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Rent rent){
this.target=rent;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理的实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
//动态代理的本质,就是使用反射机制实现的!
Object result = method.invoke(target, args);
return result;
}
//这里自己可以拓展自己需要的业务
public void log(String msg){
System.out.println("执行了" + msg + "的方法");
}
}