代理模式
- 一、代理模式作用
业务逻辑上线使用后,如果还有一些另外的与原本逻辑无关的需求,并且尽量不要改动原本的调用方式,可以采用代理模式来进行原本业务功能的增强。 - 二、代理模式实现要素
- 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();
}
```- 结果
可以看出,jdk的动态代理有一个关键点,就是接口,只有被代理对象实现了接口的时候,jdk动态代理才可以通过实现相同接口的方式来进行代理对象的生成,从而实现功能的扩展。那么,如果需要被代理的对象hello, world =================below is dynamic proxy mode==================== proxy method begin hello, world proxy method end
- 代码
-
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();
}
```- 结果
可以看到,cglib代理的实现方式与jdk动态代理是完全不同的,究其原理来说,jdk动态代理是通过实现接口的方式来实现代理对象的生成,而cglib代理,不需要接口,它是通过继承的方式来实现代理对象的生成。hello, world =================below is cglib proxy mode==================== proxy method begin hello, world proxy method end
- 代码
-