设计模式目录:https://blog.youkuaiyun.com/qq_52681418/article/details/114828850
设计模式-代理模式
代理模式代理一个类,不修改类而增加类的功能。
几种代理模式的比较
- jdk静态代理:需要类、代理器类必须继承同一个接口。
- jdk动态代理:需要类、代理器类都必须继承接口(不同一个)。
- cglib动态代理:代理器继承接口。
1.静态代理
你有一个类已经写好了,不能修改了,你想扩展它该怎么办呢?
你在写这个类的时候,让它继承一个接口,然后创建一个代理器,代理器管理这个类并添加更多的功能。
1.这是你写好的类继承的接口(或继承抽象类)
public interface ParentInterFace {
void show();
}
2.这是你的类
public class Goods implements ParentInterFace {
public void show() {
System.out.println("这是一个不能修改的类");
}
}
3.创建一个代理器,代理器需要指定代理的目标,因此传入,并且代理器实现目标类实现的接口
public class Poxy implements ParentInterFace {
protected ParentInterFace goods;
public Poxy(ParentInterFace goods) {
this.goods = goods;
}
//代理
public void show() {
System.out.println("---执行前扩展");
goods.show();
System.out.println("---执行后扩展");
}
}
启动代理步骤
public class Main { public static void main(String[] args) { ParentInterFace goods = new Goods(); //创建一个类 ParentInterFace goods2 = new Poxy(goods); //代理该类 goods2.show();//输出结果 } }
结果
代理模式和装饰者模式很像,装饰者模式类为代理器创建子类,由子类扩展
这样做需要代理类、目标类都实现同一个接口或继承同一个抽象类,但有时候我们不想让它们继承同一个接口,我们如何代理呢?
此时我们就需要jdk动态代理、cglib来实现
2.JDK动态代理
代理器实现 InvocationHandler 接口
1.你的接口:必须有接口,只不过代理器不用实现
public interface ParentInterFace {
void show();
}
1.一个普通类
public class Goods implements ParentInterFace{
public void show() {
System.out.println("这是一个类");
}
}
2.代理器:实现InvocationHandler 接口,并实现invoke方法,在此方法中进行代理
public class Poxy implements InvocationHandler {
protected ParentInterFace goods;
//传入目标类
public Poxy(ParentInterFace goods) {
this.goods = goods;
}
//继承的调用器(实现代理)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("---执行前扩展");
Object invoke=method.invoke(goods,args);
System.out.println("---执行后扩展");
return invoke;
}
}
invoke实际上通过反射调取对象的方法。
开始代理
public class Main { public static void main(String[] args) { ParentInterFace goods=new Goods(); //创建一个类 InvocationHandler poxy=new Poxy(goods); //代理 ClassLoader classLoader=poxy.getClass().getClassLoader();//获取代理类的类加载器 Class<?>[] classes=goods.getClass().getInterfaces(); //获取目标类实现的接口 ParentInterFace goods2= (ParentInterFace) Proxy.newProxyInstance(classLoader,classes,poxy);//创建jdk代理对象 goods2.show(); } }
结果
3.CGlib动态代理
可在运行期扩展java类和实现java接口,底层通过使用字节码处理框架ASM,来转换字节码并生成新的类。
- spring的AOP就是使用cglib动态代理实现的。
- Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。
cglib是一个工具,使用它你需要引入依赖:maven依赖如下
<dependency> <groupId>net.sourceforge.cglib</groupId> <artifactId>com.springsource.net.sf.cglib</artifactId> <version>2.1.3</version> </dependency>
cglib是通过构建目标类的子类,然后子类拦截父类方法来实现代理的。使用cglib,目标类不需要继承接口。
1.你的类
public class Goods{
public void show() {
System.out.println("这是一个类");
}
}
2.代理类,继承接口MethodInterceptor
默认情况会代理Goods的全部方法,你可在这里添加一条判断来决定代理哪些方法。
public class Poxy implements MethodInterceptor {
//代理方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("---扩展了方法---:"+method.getName());
System.out.println("---执行前扩展");
Object invoke=methodProxy.invokeSuper(o,objects);
System.out.println("---执行后扩展");
return invoke;
}
}
方法的返回值不知道是什么,没法获取该对象的类,返回null也不影响正常代理
开始代理
public class Main {
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(Goods.class); //继承目标类
enhancer.setCallback(new Poxy()); //设置回调
Goods goods= (Goods) enhancer.create(); //获取goods
goods.show();
}
}
实现: