目录
1.拦截器
由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。
用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor
package com.learn.interceptor;
import java.lang.reflect.Method;
public interface Interceptor {
/**真实对象前调用
* @param proxy:proxy代理对象
* @param target:真实对象
* @param method:method方法
* @param args:运行方法参数
* @return
* */
public boolean before(Object proxy, Object target, Method method,Object[] args);
/**
* @param proxy:proxy代理对象
* @param target:真实对象
* @param method:method方法
* @param args:运行方法参数
* */
public void around(Object proxy, Object target, Method method,Object[] args);
/**
* @param proxy:proxy代理对象
* @param target:真实对象
* @param method:method方法
* @param args:运行方法参数
* */
public void after(Object proxy, Object target, Method method,Object[] args);
}
这里定义了3个方法,before、around、after方法,分别给予这些方法如下逻辑定义。
- ·3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数。
- ·before 方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法。
- ·在before方法返回为false的情况下,调用around方法。
- ·在反射真实对象方法或者around方法执行之后,调用after方法。
实现这个Interceptor的实现类—Mylnterceptor
package com.learn.interceptor;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.err.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.err.println("反射方法后逻辑");
}
}
它实现了所有的Interceptor 接口方法,使用JDK动态代理,就可以去实现这些方法在适当时的调用逻辑了。
在JDK动态代理中使用拦截器
package com.learn.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;
}
/**
* 绑定委托对象并返回一个代理占位
* @param: target 真实对
* @return 代理对象占位
* */
public static Object bind(Object target,String interceptorClass){
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),
new InterceptorJdkProxy(target,interceptorClass));
}
/**
* 通过代理对象调用方法,首先进入这个方法
* @param proxy 代理对象
* @param method 方法 被调用方法
* @param args 方法的参数
* */
@Override
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();
//调用前置方法
if(interceptor.before(proxy,target,method,args)){
//反射原有对象方法
result=method.invoke(target,args);
}else{
//返回false执行around方法
interceptor.around(proxy,target,method,args);
}
//调用后置方法
interceptor.after(proxy,target,method,args);
return result;
}
}
这里有两个属性,一个是target,它是真实对象;另一个是字符串interceptorClass,它是一个拦截器的全限定名。解释一下这段代码的执行步骤。
- 第1步,在bind方法中用JDK动态代理绑定了一个对象,然后返回代理对象。
- 第2步,如果没有设置拦截器,则直接反射真实对象的方法,然后结束,否则进行第3步。
- 第3步,通过反射生成拦截器,并准备使用它。
- 第4步,调用拦截器的before方法,如果返回为true,反射原来的方法;否则运行拦截器的around方法。
- 第5步,调用拦截器的after方法。
- 第6步,返回结果。
拦截器可以进一步简化动态代理的使用方法,使程序变得更简单
测试MyInterceptor 拦截器
package com.learn.interceptor;
import com.learn.proxy.HelloWorld;
import com.learn.proxy.HelloWorldImpl;
public class Test {
public static void main(String[] args) {
HelloWorld proxy= (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.learn.interceptor.MyInterceptor");
proxy.sayHelloWorld();
}
}
运行zhe'这段代码,得到以下结果
2.责任链模式
当一个对象在一条链上被多个拦截器拦截处理(拦截器也可以选择不拦截处理它)时,我们把这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景。
定义三个拦截器
package com.learn.interceptor;
import java.lang.reflect.Method;
public class Interceptor1 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器1]before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器1]的after方法");
}
}
------
package com.learn.interceptor;
import java.lang.reflect.Method;
public class Interceptor2 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器2]before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器2]的after方法");
}
}
------
package com.learn.interceptor;
import java.lang.reflect.Method;
public class Interceptor3 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器3]before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("[拦截器3]的after方法");
}
}
测试责任链模式上的多拦截器
package com.learn.interceptor;
import com.learn.proxy.HelloWorld;
import com.learn.proxy.HelloWorldImpl;
public class TestInterceptor {
public static void main(String[] args) {
HelloWorld proxy1= (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.learn.interceptor.Interceptor1");
HelloWorld proxy2= (HelloWorld) InterceptorJdkProxy.bind(proxy1,"com.learn.interceptor.Interceptor2");
HelloWorld proxy3= (HelloWorld) InterceptorJdkProxy.bind(proxy2,"com.learn.interceptor.Interceptor3");
proxy3.sayHelloWorld();
}
}
运行结果为
before方法按照从最后一个拦截器到第一个拦截器的加载顺序运行,而after方法则按照从第一个拦截器到最后一个拦截器的加载顺序运行。
从代码中可见,责任链模式的优点在王我们可以在传递链上加入新的拦截器,增加拦截逻辑,其缺点是会增加代理和反射,而代理和反射的性能不高。