一, 概述
1, 代理模式是常用的 java 设计模式, 生成一个代理对象, 来代替真正的对象, 从而控制真实对象的访问.
客户 (调用者)---------- 商务 (代理对象)----------- 软件工程师 (真正对象)
2, 我们需要在调用者调用对象之前就生成一个代理对象, 而这个代理对象需要和真正对象建立代理关系
----- 代理对象和真正对象建立关系
----- 实现代理对象的代理逻辑方法
3, 常用的代理对象方法: JDK 动态代理, CGLIB
二, JDK 动态代理
JDK 动态代理所用到的代理类在程序调用到代理类对象时才由 JVM 真正创建, JVM 根据传进来的 业务实现类对象以及方法名 , 动态地创建了一个代理类的 class 文件并被字节码引擎执行, 然后通过该代理类对象进行方法调用.
1, 需要借助接口生成代理对象
- public interface HelloWorld {
- public void sayHelloWorld();
- }
- public class HelloWorldImp implements HelloWorld{
- @Override
- public void sayHelloWorld() {
- System.out.println("你好");
- }
- }
2, 实现代理逻辑类: 需要实现 java.lang,reflect.InvocationHandler 接口, 重写 invoke 方法
- package reflect;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import org.junit.Test;
- public class JdkProxyExample implements InvocationHandler{
- // 真实对象
- private Object target = null;
- // 建立关系, 返回代理对象
- public Object bind(Object target) {
- this.target = target;
- return Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(),this);
- }
- @Override
- // 处理代理实例上的方法调用并返回结果. 当在与其关联的代理实例上调用方法时, 将在调用处理程序上调用此方法.
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("调用真实对象服务之前的服务");
- Object obj = method.invoke(target, args);// 相当于调用 sayHelloWorld()
- System.out.println("调用真实对象服务之后的服务");
- return obj;
- }
- @Test
- public void testJdkProxyExample() {
- JdkProxyExample jdkProxyExample = new JdkProxyExample();
- HelloWorld proxy = (HelloWorld) jdkProxyExample.bind(new HelloWorldImp());
- proxy.sayHelloWorld();
- }
- }
1, 该方法返回指定接口的代理类的实例, 该接口将方法调用分派给指定的 invocationhandler 代理
- public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
- throws IllegalArgumentException
参数: InvocationHandler 是由代理实例的调用处理程序实现的接口. 每个代理实例都有一个关联的调用处理程序. 当在代理实例上调用方法时,
方法调用被编码并发送到其调用处理程序的 invokemethod.
2,Object invoke(Object proxy, Method method,Object[] args) throws Throwable{}
处理代理实例上的方法调用并返回结果. 当在与其关联的代理实例上调用方法时, 将在调用处理程序上调用此方法.
参数: Object proxy : 就是 newProxyInstance 返回的代理对象
Method method : 当前调度的接口中的方法
Object[] args : 调度方法中的参数
通俗点说就是实现 java.lang,reflect.InvocationHandler 接口, 重写 invoke 方法, 但是重写 invoke() 需要给它三个参数
参数一: Object proxy : 需要通过 newProxyInstance 返回的获取参数 proxy
三, CGLIB 动态代理
1,cglib 是针对类来实现代理的, 原理是对指定的业务类生成一个子类, 并覆盖其中业务方法实现代理. 因为采用的是继承, 所以不能对 final 修饰的类进行代理.
(1) 首先定义一个 y 业务类 Hello
- public class Hello {
- public void sayHello() {
- System.out.println("hello...");
- }
- }
(2) 对指定的业务类生成一个子类, 并覆盖其中业务方法实现代理.
- package reflect;
- import java.lang.reflect.Method;
- import org.junit.Test;
- import.NET.sf.cglib.proxy.Enhancer;
- import.NET.sf.cglib.proxy.MethodInterceptor;
- import.NET.sf.cglib.proxy.MethodProxy;
- public class CGLIBProxyExample implements MethodInterceptor{
- // 生成代理对象
- public Object getProxy(Class cls) {
- // 增强类
- Enhancer enhance = new Enhancer();
- // 设置增强的父类, 即业务类
- enhance.setSuperclass(cls);
- /*setCallback() 设置哪个类是它的代理类, 参数是 this 为当前对象,
- * 要求当前对象实现 MethodInterceptor 接口并实现方法 intercept*/
- enhance.setCallback(this);
- return enhance.create();
- }
- @Override
- public Object intercept(Object proxy,Method method,Object[]args,
- MethodProxy methodProxy) throws Throwable {
- System.out.println("前");
- Object result = methodProxy.invokeSuper(proxy, args);
- System.out.println("后");
- return result;
- }
- @Test
- public void testCGLIBProxyExample() {
- CGLIBProxyExample cglibProxyExample = new CGLIBProxyExample();
- Hello proxy = (Hello) cglibProxyExample.getProxy(Hello.class);
- proxy.sayHello();
- }
- }
MethodInterceptor, Enhancer 在 cglib-nodep-3.2.10.jar 下
四, 拦截器
1, 因为拦截器可以进一步简化动态代理的使用方法, 是程序变得更简单.
2, 实现步骤:(1) 定义一个拦截器接口
(2) 定义拦截器的实现类
(3) 实现拦截器的逻辑
- public interface Interceptor {
- public boolean before(Object proxy,Object target,Method method,Object[] args);
- public void around(Object proxy,Object target,Method method,Object[] args);
- public void after(Object proxy,Object target,Method method,Object[] args);
- }
- package interceptor;
- import java.lang.reflect.Method;
- public class InterceptorImp implements Interceptor{
- @Override
- /* 当返回值为 true 时, 反射真实对象原来的方法
- * 当返回值为 false 时, 则调用 around 方法
- */
- public boolean before(Object proxy, Object target, Method method, Object[] args) {
- System.out.println("反射方法前逻辑");
- return false;
- }
- @Override
- // 对原来的方法不满意, 进行调整
- public void around(Object proxy, Object target, Method method, Object[] args) {
- System.out.println("取代原方法的逻辑");
- }
- @Override
- public void after(Object proxy, Object target, Method method, Object[] args) {
- System.out.println("调用原方法或 around 后还要执行的逻辑");
- }
- }
- package interceptor;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;public class InterceptorJdkProxy implements InvocationHandler{
- private Object target;
- private String interceptorClass = null;// 定义拦截器类路径
- public InterceptorJdkProxy(Object target,String interceptorClass) {
- this.target = target;
- this.interceptorClass = interceptorClass;
- }
- public static Object bind(Object target,String interceptorClass) {
- return Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(),
- new InterceptorJdkProxy(target,interceptorClass));
- }
- @Override
- // 第一个参数 proxy 的获取通过 Proxy.newProxyInstance() 获取
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if(interceptorClass==null) {
- // 没有拦截器就直接反射原来方法
- return method.invoke(target, args);
- }
- // 否则, 通过反射生成拦截器
- Object result = null;
- Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
- // 判断 before 方法
- if(interceptor.before(proxy, target, method, args)) {
- result = method.invoke(target, args);
- }else {
- interceptor.around(proxy, target, method, args);
- }
- interceptor.after(proxy, target, method, args);
- return result;
- }
- public static void main(String[] args) {
- // 没有使用代理
- HelloWorld helloWorld = new HelloWorldImp();
- helloWorld.sayHelloWorld();
- // 使用了代理
- HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImp(),
- "interceptor.InterceptorImp");
- proxy.sayHelloWorld();
- }
- }
来源: http://www.bubuko.com/infodetail-3044914.html