Use JDK dynamic proxy implementation interceptor

Principles of Programming AOP (Aspect Oriented Programming) is a dynamic proxy mode, use JDK dynamic proxy target object implements an interface, use cglib when no dynamic proxy that implements the interface. Implement the Interceptor is typical section oriented programming. Programmer designed an interceptor interface for developers to use, developers only know how interceptor interface, meaning and effect without the need to know the specific implementation.
The following interceptor write a look at its implementation.

Defines interception interfaces Intercepter

public interface Intercepter {
    boolean before(Object proxy, Method method, Object[] args);
    void around(Object proxy, Method method, Object[] args);
    void after(Object proxy, Method method, Object[] args);
}

This defines three methods, before, around, after, and several similar notification logic spring. Logic is defined as follows:

  • Parameter 3 method is: proxy proxy object, target real object, method method, args method operating parameters
  • before method returns a boolean value, it calls the method invocation before the target, when it returns true, the method of reflecting the real object, calling around the method returns false.
  • In the case before the method returns false, call the method in place around the target method.
  • Call after method after method or around real reflection method.

Call the above logic defined by the program designers, developers need to implement Intercepter interfaces, custom concrete realization of three methods. That is, a custom interceptor.

Custom interceptors

The following three definitions interceptors, MyIntercepter1, MyIntercepter2, MyIntercepter3. Structure is as follows, just a different name, only posted one:

public class MyIntercepter1 implements Intercepter{

    /**
     * 目标方法调用前调用
     * @return true:调用目标方法;false:调用around方法取代目标方法
     */
    @Override
    public boolean before(Object proxy, Method method, Object[] args) {
        System.out.println("MyIntercepter1 ==> before execute!!");
        return true;
    }

    /**
     * before方法返回false调用
     */
    @Override
    public void around(Object proxy, Method method, Object[] args) {
        System.out.println("MyIntercepter1 ==> around execute!!");
    }

    /**
     * 目标方法或around方法调用后调用
     */
    @Override
    public void after(Object proxy, Method method, Object[] args) {
        System.out.println("MyIntercepter1 ==> after execute!!");
    }
}

This is the developer writes interceptors. See how it is in force:

The use of dynamic proxy to use interceptors

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class IntercepterProxyHandler implements InvocationHandler {
    private Object target;//目标对象
    private String intercepterClass;//拦截器全限定名

    private IntercepterProxyHandler(Object target, String intercepterClass){
        this.target = target;
        this.intercepterClass = intercepterClass;
    }

    /**
     * 绑定目标对象,并对外暴露获取代理对象的方法
     * @param target 目标对象
     * @param intercepterClass 拦截器类全限定名称
     * @return 代理对象
     */
    public static Object bind(Object target,String intercepterClass){
        return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                target.getClass().getInterfaces(),
                new IntercepterProxyHandler(target,intercepterClass));
    }

    /**
     * 拦截器逻辑
     * @param proxy 代理对象
     * @param method 目标方法
     * @param args 方法的参数
     * @return 调用结果
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        //如果未指定拦截器,则只执行目标方法
        if (this.intercepterClass==null){
            return method.invoke(target,args);
        }
        Intercepter intercepter = (com.youzi.test.proxy.intercepter.Intercepter) Class.forName(intercepterClass).newInstance();
        //执行拦截器before方法,如果返回true,则再执行目标方法;如果返回false,则执行around方法
        if (intercepter.before(proxy, method, args)){
            result = method.invoke(target,args);
        }else{
            intercepter.around(proxy, method, args);
        }
        //再执行after方法
        intercepter.after(proxy, method, args);
        return result;
    }
}

This class inherits InvocationHandler class, there are two properties, one is the real target objects; twenty-one is intercepterClass, it is the fully qualified name of an interceptor.
Provide external bind method that returns a proxy object; achieve invoke method InvocationHandler class defines the logical call interceptor.
Specific implementation steps:

  1. Call the bind method bind an object with the jdk dynamic proxy, then return proxies, the target audience of the method enhanced.
  2. Use a proxy object to call the target method, the method executes invoke logic. If the interceptor is not set, then the method directly reflected the real object. Otherwise, the third step
  3. Interceptor generated by reflection, and it is ready for use.
  4. before the method call interceptor, if true, reflecting the original method returns; otherwise run around method interceptors.
  5. Call interceptor after method
  6. Back to Results

Interceptor encapsulates the dynamic proxy code, further simplifies the use of dynamic proxies.
The following code uses the interceptor See, previously defined three interceptors, spend here:
the target object (not posted implement the interface):

public class IServiceImpl implements IService {
    @Override
    public void doFirst(String string) {
        System.out.println("执行第一个业务方法,参数:"+string);
    }

    @Override
    public void doSecond() {
        System.out.println("执行第二个业务方法");
    }
}

Test category

public class Test2 {
    public static void main(String[] args) {
        IService target = new IServiceImpl();
        IService proxy1 = (IService) IntercepterProxyHandler.bind(target, "com.youzi.test.proxy.intercepter.MyIntercepter1");
        IService proxy2 = (IService) IntercepterProxyHandler.bind(proxy1, "com.youzi.test.proxy.intercepter.MyIntercepter2");
        IService proxy3 = (IService) IntercepterProxyHandler.bind(proxy2, "com.youzi.test.proxy.intercepter.MyIntercepter3");
        proxy3.doFirst("aaaa");
    }
}

As used herein the chain of responsibility pattern, to target an orderly method to add three interceptors. Results of the:

MyIntercepter3 ==> before execute!!
MyIntercepter2 ==> before execute!!
MyIntercepter1 ==> before execute!!
执行第一个业务方法,参数:aaaa
MyIntercepter1 ==> after execute!!
MyIntercepter2 ==> after execute!!
MyIntercepter3 ==> after execute!!

Because the three interceptors before method returns true, there is no method of execution around. If you modify MyIntercpter2 before the method returns false, then the results:

MyIntercepter3 ==> before execute!!
MyIntercepter2 ==> before execute!!
MyIntercepter2 ==> around execute!!
MyIntercepter2 ==> after execute!!
MyIntercepter3 ==> after execute!!
Published 43 original articles · won praise 17 · views 30000 +

Guess you like

Origin blog.csdn.net/weixin_41172473/article/details/92768360