【Spring】Spring学习笔记---拦截器-责任链设计模式

一.简介

把方法执行的生命周期抽取出来try…catch…finally
把代理模式从抽象的逻辑转化成五个时间节点,把interceptorName传进来后,代理流程什么都不做,所有流程和方法交给拦截器做

二.案例

1.先创建拦截器,接口Interceptor

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public interface Interceptor {
    /**
     * 方法执行之前做检测,如果返回为false 那么方法终止
     */
    Boolean before(Object target, Object proxy, Method method, Object[] args);

    /*返回方法执行结果*/
    Object around(Object target,Object proxy,Method method,Object[] args) throws InvocationTargetException, IllegalAccessException;

    /**
     * 方法执行之后,需要将方法执行之后的结果传入
     */
    void afterReturning(Object target,Object proxy,Method method,Object[] args,Object result);

    /**
     * 方法发生异常之后,需要将异常的对象传进来
     */
    void afterThrowing(Object target,Object proxy,Method method,Object[] args,Exception e);

    void after(Object target,Object proxy,Method method,Object[] args);
}

2.创建实现类InterceptorImpl1

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

//用InterceptorImpl1处理JDKProxyProcessor
public class InterceptorImpl1 implements  Interceptor{
    //方法执行前进行判断
    @Override
    public Boolean before(Object target, Object proxy, Method method, Object[] args) {
        return true;
    }
	//方法执行中
    @Override
    public Object around(Object target, Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        Object result = method.invoke(target,args);
        return result;
    }
	//记录日志
    @Override
    public void afterReturning(Object target, Object proxy, Method method, Object[] args, Object result) {
        System.out.println(new Date() + "use args" +
                Arrays.toString(args) + "use " + method.getName() + " get " + result + " as result");
    }
	
    @Override
    public void afterThrowing(Object target, Object proxy, Method method, Object[] args, Exception e) {

    }

    @Override
    public void after(Object target, Object proxy, Method method, Object[] args) {

    }
}

3.创建代理工厂JDKProxyFactory

import java.lang.reflect.Proxy;

public class JDKProxyFactory {

    //传入target 目标对象
    //return 获得代理对象
    public static Object bind(Object target){
        //返回代理实例
        //getClassLoader类加载器,getInterfaces所有的接口,获取这两个之后创建对象
        //getInvocationHandler增强原始对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),new JDKProxyProcessor(target));
    }

    public static Object bind(Object target, String interceptorName){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),new JDKProxyProcessor(target,interceptorName));
    }
}

4.创建InvocationHandler的子实现类JDKProxyProcessor

import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

//InvocationHandler的子实现
public class JDKProxyProcessor implements InvocationHandler {

    private  Object target;

    public JDKProxyProcessor(Object target) {
        this.target = target;
    }

    public JDKProxyProcessor() {
    }

    private String interceptorName;//接收Interceptor
    public JDKProxyProcessor(Object target, String interceptorName) {
    	this.target = target;
        this.interceptorName = interceptorName;
    }

    /*
    * proxy:代理对象
    * method:原始对象中的每一个方法 add方法
    * args:原始对象被调用的时候的参数 参数a,b
    * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = null;

        //把代理模式从抽象的逻辑转化成五个时间节点,把interceptorName传进来后,代理流程什么都不做,所有流程和方法交给拦截器做
        if (StringUtils.hasText(interceptorName)){ //判断是否有这个接口名称,也就是是否有该拦截器
            //根据名字创建
            Interceptor interceptor = (Interceptor)Class.forName(interceptorName).newInstance();
            //方法执行的生命周期
            try {
                if (interceptor.before(target,proxy,method,args)){
                    //抽取拦截器的5个时间节点,使用这些节点拦截invoke
                    result = interceptor.around(target,proxy,method,args);
                    interceptor.afterReturning(target,proxy,method,args,result); //返回之后
                }else {
                    throw new RuntimeException("前置拦截返回为false ,方法终止");
                }
            }catch (Exception e){
                interceptor.afterThrowing(target,proxy,method,args,e); //最终
            }finally {
                interceptor.after(target,proxy,method,args);
            }
        }else {//若没有拦截器则按之前的逻辑走
            System.out.println("before");
            result = method.invoke(target,args);

            System.out.println(new Date() + "use args" +
                    Arrays.toString(args) + "use " + method.getName() + " get " + result + " as result");

        }
        return result;
    }
}

5.创建UserMapperInterface

public interface UserMapperInterface {
    void sayHello();

    int add(int a,int b);
}

6.创建实现类

public class UserMapper implements UserMapperInterface {

    @Override
    public void sayHello(){
        System.out.println("hello");
    }

    @Override
    public int add(int a, int b) {
        return a+b;
    }
}

7.创建ProxyMain类

public class ProxyMain {
    public static void main(String[] args) {
    
        UserMapper userMapper=new UserMapper();

        Interceptor interceptor = new InterceptorImpl1();
        //把原始对象和拦截器名字传进去
        UserMapperInterface proxyUserMapper1 = (UserMapperInterface) JDKProxyFactory.bind(userMapper,interceptor.getClass().getName());
        UserMapperInterface proxyUserMapper2 = (UserMapperInterface) JDKProxyFactory.bind(proxyUserMapper1,interceptor.getClass().getName());
        proxyUserMapper2.sayHello();
        System.out.println(proxyUserMapper2.add(1,2));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值