1. 几种常见的代理模式
代理模式定义:为其他对象提供一种代理以控制这个对象的访问。
代理模式结构:
Subject:抽象主题类,声明真实主题与代理的共同接口方法。
RealSubject:真实主题类,定义了代理所表示的真实对象,客户端通过代理类间接的调用真实主题类的方法。
ProxySubject:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
Client:客户端类。
代理模式分类:
1. 静态代理:在代码运行前就已经存在了代理类的class编译文件。
2. 动态代理:动态代理则是在代码运行时通过反射来动态的生成代理类的对象,并确定到底来代理谁。
3. Cglib代理:Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
2.静态代理模式
场景:订外卖(不自己买外卖,让同事帮忙订外卖)
订外卖接口( Subject:抽象主题类)
public interface ITakeaway {
//订外卖
void order();
}
代理类(ProxySubject:代理类)
public class OrderProxy implements ITakeaway {
private ITakeaway mTake;
public OrderProxy (ITakeaway take){
mTake=take;
}
@Override
public void order() {
mTake.order();
}
}
被代理类( RealSubject:真实主题类)
public class Author implements ITakeaway {
@Override
public void order() {
System.out.println("订外卖");
}
}
调用类( Client:客户端类)
public class Test {
public static void main(String[] args){
//创建author
ITakeaway author=new Author ();
//创建代购者并将author作为构造函数传参
ITakeaway ordering=new OrderProxy (author);
ordering.buy();
}
}
小结:代理类包含了被代理类,最终调用的都是被代理类实现的方法
3.动态代理模式
Java提供了动态的代理接口InvocationHandler,实现该接口需要重写invoke()方法。
动态代理类
public class DynamicOrdering implements InvocationHandler{
private Object obj;
public DynamicOrdering (Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(obj, args);
return result;
}
}
调用类
public class Test {
public static void main(String[] args){
//创建author
ITakeaway author=new Author ();
//创建动态代理
DynamicOrdering mDynamicOrdering=new mDynamicOrdering(author);
//创建Author的ClassLoader
ClassLoader loader=author.getClass().getClassLoader();
//动态创建代理类
ITakeaway ordering= (ITakeaway ) Proxy.newProxyInstance(loader,new Class[]{ITakeaway .class},mDynamicOrdering);
ordering.buy();
}
}
4.cglib代理模式
为何使用cglib: JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现。Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类。
Cglib子类代理实现的注意事项: 代理的类不能为final,否则报错
代码场景:使用cglib模拟spring的AOP事务管理
被代理类( RealSubject:真实主题类)
public class PayDao {
public void savePayRecord() {
System.out.println("----支付成功,已经保存数据!----");
}
}
Cglib代理工厂:ProxyFactory.java(动态代理类:ProxySubject)
public class ProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务...");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
}
测试类(客户端类:Client)
public class App {
@Test
public void test(){
//目标对象
PayDao target = new PayDao ();
//代理对象
PayDao proxy = (PayDao )new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.savePayRecord();
}
}