代理模式
1、为什么要学代理模式:
代理模式是spring AOP的底层【springAOP和springMVC】
2、代理模式分类:
Ⅰ、静态代理
- 角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真是角色:被代理的角色
- 代理角色:代理真实角色,代理后我们一般会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
1、接口
public interface Rent {
public void rent();
}
2、真实角色
public class Host implements Rent{
public void rent() {
System.out.println("我是房东,我要出租房子");
}
}
3、代理角色
public class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
public Proxy() {
}
public void rent() {
host.rent();
}
}
4、客户端访问代理角色
public class Client {
public static void main(String[] args) {
Host host=new Host();
Proxy p=new Proxy(host);
//直接找中介
p.rent();
}
}
代理模式的好处:
- 可以使得真实角色业务更加纯粹,不用去关注一些工共的事务
- 工共的业务交给代理角色,实现了业务的分工
- 工共业务发生扩展的时候,方便集中管理
代理模式缺点:
- 一个真实角色就会产生一个代理角色:代码量会翻倍,开发效率会变低
Ⅱ、动态代理
- 动态代理和静态代理是一样的
- 动态代理的代理类是动态生成的,不是我们直接写
- 动态代理分两大类,基于接口的动态代理,基于类的动态代理类
- 基于接口:JDK动态代理
- 基于类:cglib
- Java字节码实现:Javassist
需要了解的两个类:
proxy:代理
提供了动态代理类和实例的静态方法,它是由这些方法创建的所有动态代理类的超类
提供四个方法:getInvoationHandler(object proxy),newproxyInstance(Classloader loader)
InvocationHandler:调用 处理程序
是反射包下的:java.lang.reflect reflect(反射)
只有一个方法:invoke{object proxy,方法,method,Object[] args}
【注意】
InvocationHandler是接口,用来实现,Proxy是用来生成代理对象
–proxy 该方法的代理实例
–method调用这个类上的方法,也可以是一个接口
–args:固定的方法里面传递什么参数
动态代理的好处:
- 可以使真是角色操作更加纯粹,不用去处理一些公共的事务
- 公共事务也就交给代理角色,实现了业务的分工
- 公共业务发生扩展时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般对应一类业务
- 一个动态代理类可以代理多个类,只要实现多个接口即可!
程序流程
接口Rent
public interface Rent {
public void rent();
}
真实角色
public class Host implements Rent{
public void rent(){
System.out.println("我是房东,我要出租房子");
}
}
ProxyInvocationHandler
//我们会用这个类实现自动生成代理类
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);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质就是使用反射实现的
Object result=method.invoke(rent,args);
return result;
}
}
当然上面ProxyInvocationHandler也可以 写成一个工具类,用Object实现,就可以任意调用了
package com.asiainfo.demo4;
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(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(target,args);
return result;
}
}
Client(客户端)
public class Client {
public static void main(String[] args) {
//真实角色
Host host= new Host();
//代理角色,我们暂时没有
ProxyInvocationHandler pih=new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
pih.setRent(host);
//下面的proxy是动态生成的我们并没有去写。
Rent proxy=(Rent) pih.getProxy();
proxy.rent();
}
}
总结
1、创建接口
2、创建真实对象
3、代理接口实现InvocationHandler,然后在实现InvacationHandler的类下面,用Proxy获取代理对象。
4、客户端调用,真实角色,代理角色,但是没有代理角色,所以通过InvacationHandler接口的实现类下面的getProxy()方法获取代理对像proxy,利用set注入真实对象,然后动态生成代理对象,如:Rent proxy=(Rent) pih.getProxy();之后直接点就出来了如,proxy.rent();