代理
Java中有一个经典的设计模式叫做代理模式(Proxy),在我们平时开发和框架源码中无处不在。
这里可以看到,代理模式并没有改变对象A,而是换了一种方式访问对象A的方法,通过代理对象ProxyA来访问对象A,这样做的好处是——在A的基础上拓展,实现它的额外附加功能。
静态代理
创建一个接口ICar ,里面有一个run 方法,然后定义宝马的实现类来实现它:
public interface ICar {
void run();
}
public class BmwCar implements ICar {
@Override
public void run() {
System.out.println("宝马车跑起来了。");
}
}
因为汽车需要启动才能跑,跑完以后需要熄火,毕竟油价挺贵的。新建一个CarProxy 类:
public class CarProxy implements ICar {
private ICar target;
public CarProxy(ICar target) {
this.target = target;
}
@Override
public void run() {
System.out.println("汽车启动。。。");
target.run();
System.out.println("汽车熄火。。。");
}
}
测试一下:
public class CarApp {
public static void main(String[] args) {
CarProxy carProxy = new CarProxy(new BmwCar());
carProxy.run();
}
}
运行结果如下图所示: 静态代理虽然在学习中经常会看到,但是在框架和实际编码中却不经常使用: 1.优点: 不修改目标对象的代码, 完成了目标对象的扩展。 2.缺点: 代理对象会随着目标对象的修改需要相应的修改。比如在ICar中加了接口,代理也需要做相应代码的修改。
静态代理的缺点过于明显了,有没有什么办法规避呢? 有,动态代理。
动态代理
JDK动态代理
代理类Proxy 所在包:java.lang.reflect 。核心方法是:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
调用调用该方法即可对目标对象生成对应的代理对象。 这里需要传入三个参数:
ClassLoader loader : 目标对象使用的类加载器,target.getClass().getClassLoader() Class<?>[] interfaces : 目标对象实现接口类型,使用泛型方式类型,target.getClass().getInterfaces() InvocationHandler h : 当执行目标对象的方法时,会先调用InvocationHandler 的invoke 方法, 同时把当前执行目标对象的方法作为参数传入。
ICarPro:
public interface ICarPro {
void refueling();
void run();
}
BenzProCar:
public class BenzProCar implements ICarPro {
@Override
public void refueling() {
System.out.println("给我的大奔加油!");
}
@Override
public void run() {
System.out.println("大奔跑起来了。");
}
}
CarProFactory:
public class CarProFactory {
private ICarPro target;
public CarProFactory(ICarPro target) {
this.target = target;
}
public Object genProxyBean() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--操作前");
Object returnValue = method.invoke(target, args);
System.out.println("--操作后");
return returnValue;
}
}
);
}
}
测试运行:
public class CarApp {
public static void main(String[] args) {
CarProFactory carProFactory = new CarProFactory(new BenzProCar());
ICarPro benz = (ICarPro)carProFactory.genProxyBean();
benz.refueling();
benz.run();
}
}
运行结果: JDK动态代理对象生成的类:
public class $proxy0 extends Proxy implements ICarPro
Cglib动态代理
无论是静态代理还是JDK动态代理,其本质是目标对象一定要实现一个接口。有时候我们写业务代码就是一个类,没有实现接口,这时候可以使用Cglib动态代理。 pom文件依赖引入:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
建立CGLIB动态工厂类CarProxyFactoryByCglib :
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CarProxyFactoryByCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName()+"方法调用...");
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println(method.getName()+"方法调用结束...");
return obj;
}
}
测试:
public class CarApp {
public static void main(String[] args) {
CarProxyFactoryByCglib cglibProxy = new CarProxyFactoryByCglib();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BenzProCar.class);
enhancer.setCallback(cglibProxy);
BenzProCar proxy = (BenzProCar) enhancer.create();
proxy.refueling();
System.out.println("1.加油完成");
proxy.run();
System.out.println("2.运行完成");
}
}
运行结果:
|