代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。
Java代理分为静态代理和动态代理和Cglib代理,下面进行逐个说明。
静态代理
接口类AdminService.java接口
1 | package com.lance.proxy.demo.service; |
实现类AdminServiceImpl.java
1 | package com.lance.proxy.demo.service; |
代理类AdminServiceProxy.java
1 | package com.lance.proxy.demo.service; |
测试类StaticProxyTest.java
1 | package com.lance.proxy.demo.service; |
输出:
1 | 判断用户是否有权限进行update操作 |
总结:
静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。
不足:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。
JDK动态代理
为解决静态代理对象必须实现接口的所有方法的问题,Java给出了动态代理,动态代理具有如下特点:
1.Proxy对象不需要implements接口;
2.Proxy对象的生成利用JDK的Api,在JVM内存中动态的构建Proxy对象。需要使用java.lang.reflect.Proxy类的
1 | /** |
方法,方法参数说明:
a.ClassLoader loader:指定当前target对象使用类加载器,获取加载器的方法是固定的;
b.Class<?>[] interfaces:target对象实现的接口的类型,使用泛型方式确认类型
c.InvocationHandler invocationHandler:事件处理,执行target对象的方法时,会触发事件处理器的方法,会把当前执行target对象的方法作为参数传入。
实战代码
AdminServiceImpl.java和AdminService.java和原来一样,这里不再赘述。
AdminServiceInvocation.java
1 | package com.lance.proxy.demo.service; |
AdminServiceDynamicProxy.java
1 | package com.lance.proxy.demo.service; |
DynamicProxyTest.java
1 | package com.lance.proxy.demo.service; |
输出结果:
1 | ============ 方法一 ============== |
Cglib代理
DK动态代理要求target对象是一个接口的实现对象,假如target对象只是一个单独的对象,并没有实现任何接口,这时候就会用到Cglib代理(Code Generation Library),即通过构建一个子类对象,从而实现对target对象的代理,因此目标对象不能是final类(报错),且目标对象的方法不能是final或static(不执行代理功能)。
Cglib依赖的jar包
1 | <dependency> |
实战
目标对象类AdminCglibService.java
1 | package com.lance.proxy.demo.service; |
代理类AdminServiceCglibProxy.java
1 | package com.lance.proxy.demo.service; |
Cglib代理测试类CglibProxyTest.java
1 | package com.lance.proxy.demo.service; |
输出结果:
1 | 代理对象:class com.lance.proxy.demo.service.AdminCglibService$$EnhancerByCGLIB$$41b156f9 |
总结
理解上述Java代理后,也就明白Spring AOP的代理实现模式,即加入Spring中的target是接口的实现时,就使用JDK动态代理,否是就使用Cglib代理。Spring也可以通过
本文链接: https://linbei.top/Java%E4%BB%A3%E7%90%86/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!