代理模式

一、代理模式作用
业务逻辑上线使用后,如果还有一些另外的与原本逻辑无关的需求,并且尽量不要改动原本的调用方式,可以采用代理模式来进行原本业务功能的增强。
二、代理模式实现要素
1、要有代理类和被代理类
2、代理类和被代理类实现相同的接口
3、代理类要依赖被代理类,因为需要被代理类来实现业务逻辑

三、静态代理
下面,我们就用代码的方式来展现静态代理模式的使用方式:
/**
* 简单接口
*/
public interface Hello {
public void sayHello();
}
/**
* 简单接口的实现类
*/
class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("hello, world");
}
}
/**
* 代理类,类中注入被代理对象,并进行功能的增强
*/
class HelloImplProxy implements Hello {
//被代理对象
private Hello target ;
//通过构造器注入被代理对象
public HelloImplProxy(Hello target){
this.target = target;
}
//在相同方法中调用被代理对象,并且实现功能的增强
@Override
public void sayHello() {
System.out.println("sayHello method start");
target.sayHello();
System.out.println("sayHello method end");
}
}
测试
public static void main(String[] args) {
Hello hello = new HelloImpl();
hello.sayHello();
System.out.println("=================below is proxy mode====================");
Hello helloProxy = new HelloImplProxy(hello);
helloProxy.sayHello();
}
结果
hello, world
=================below is proxy mode====================
sayHello method start
hello, world
sayHello method end
从上面的结果可以看出,被代理对象实现了基础的业务逻辑,代理对象保留了原本业务逻辑的调用,并且实现了对被代理对象的功能的增强。

四、动态代理
静态代理模式可以解决对业务逻辑进行增强需求的满足,但是会有一个问题,就是如果还有别的功能需要扩展,则需要新增新的代理类,随着需求越来越多,代理类也会越来越多。而动态代理技术则是通过动态生成java字节码的方式,将生成的字节码加载进ClassLoad,生成对应的Class对象,在通过Class对象生成普通java对象的。从而解决代理类数量爆炸的问题。下面我们就从代码层面讲解java的两种动态代理技术:
1、jdk动态代理代码
public static void main(String[] args) {
Hello hello = new HelloImpl();
// Hello helloProxy = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[]{Hello.class}, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// System.out.println("proxy method begin");
// Object ret = method.invoke(hello, args);
// System.out.println("proxy method end");
// return ret ;
// }
// });
Hello helloProxy = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[]{Hello.class},
(proxy, method, as) -> {
System.out.println("proxy method begin");
Object ret = method.invoke(hello, as);
System.out.println("proxy method end");
return ret ;
});
hello.sayHello();
System.out.println("=================below is dynamic proxy mode====================");
helloProxy.sayHello();
结果
hello, world
=================below is dynamic proxy mode====================
proxy method begin
hello, world
proxy method end
可以看出,jdk的动态代理有一个关键点,就是接口,只有被代理对象实现了接口的时候,jdk动态代理才可以通过实现相同接口的方式来进行代理对象的生成,从而实现功能的扩展。那么,如果需要被代理的对象
2、cglib代理
public static void main(String[] args) {
HelloImpl hello = new HelloImpl();
hello.sayHello();
System.out.println("=================below is cglib proxy mode====================");
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(hello.getClass().getClassLoader());
enhancer.setSuperclass(HelloImpl.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("proxy method begin");
Object ret = method.invoke(hello, objects);
System.out.println("proxy method end");
return ret;
}
});
HelloImpl helloCglibProxy = (HelloImpl) enhancer.create();
helloCglibProxy.sayHello();
结果
hello, world
=================below is cglib proxy mode====================
proxy method begin
hello, world
proxy method end
可以看到,cglib代理的实现方式与jdk动态代理是完全不同的,究其原理来说,jdk动态代理是通过实现接口的方式来实现代理对象的生成,而cglib代理,不需要接口,它是通过继承的方式来实现代理对象的生成。
原文链接:https://blog.csdn.net/whhwch1986/article/details/113399055