SSM框架学习笔记day3---动态代理&拦截器

3.1动态代理

/***********************************
意义:生成一个代理对象来代理真实对象,管理真实对象的访问

示意图SSM框架学习笔记day3---动态代理&拦截器_第1张图片
代理对象负责按照一定规则对客户的请求进行拦截

代理必须分为两个步骤:

1.代理对象和真实对象建立代理关系
2.实现代理对象的代理逻辑方法

3.1.1JDK动态代理

包:java.lang.reflect.*

接口

public interface HelloWorld {
    public void say();
}

实现类

public class HelloWorldImpl implements HelloWorld{

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

1:建立代理对象和真是服务对象的关系
2:实现代理逻辑
代理类如下:

public class JdkProxyExample implements InvocationHandler {
    
    //真实的对象
    private Object target = null;
    
    /**
     * 建立代理关系  返回代理对象
     * @param target 真实对象
     * @return 代理对象*/
    public Object bind(Object target){
        this.target = target;
        //newProxyInstance包含三个参数:
        //类加载器 生成的代理对象需要实现的接口 代理类	
        return Proxy.newProxyInstance(target.getClass()
                .getClassLoader(),target.getClass().getInterfaces(),this);
    }
    
    /**
     * 代理方法逻辑
     * @param proxy 代理对象
     * @param method 当前调度方法
     * @param args 当前方法参数
     * @return 代理结果返回
     * @throws Throwable*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理逻辑方法");
        System.out.println("调度真实对象前的服务");
        //invoke参数:
        //代理对象(bind生成的)  当前调度的方法(反射实现)  调度方法的参数
        Object obj = method.invoke(target,args);//相当于调用say
        System.out.println("调度真实对象后的服务");
        return obj;
    }
}

客户端测试:

public class JdkProxyTest {
    public static void main(String[] args){
        JdkProxyExample obj = new JdkProxyExample();
        //绑定
        HelloWorld proxy = (HelloWorld)obj.bind(new HelloWorldImpl());
        proxy.say();
    }
}

SSM框架学习笔记day3---动态代理&拦截器_第2张图片

3.1.2CGLIB动态代理

JDK必须要提供接口才可以使用,但CGLIB只要一个非抽象类就可以实现动态代理
前提:导入cglib相关jar包

package reflect;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLIB implements MethodInterceptor {
    /**
     * 生成代理对象
     * @param cls  Class
     * @return class类的代理对象*/
    public Object getProxy(Class cls){
        //enhancer增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型
        enhancer.setSuperclass(cls);
        //定义代理逻辑对象为当前对象,要求MehodInterceptor方法
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    /**
     * 代理逻辑方法
     * @param methodProxy
     * @param proxy
     * @param objects
     * @param method
     * @return 代理逻辑返回
     * @throws Throwable*/
    @Override
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用前");
        //cglib反射调用真实方法
        Object res = methodProxy.invokeSuper(proxy,objects);
        System.out.println("调用后");
        return res;
    }
}

3.2拦截器

隐藏了动态代理逻辑,供开发者直接实现

拦截器的实现和使用:

定义一个拦截器接口:

package Interceptor;

import java.lang.reflect.Method;

public interface Interceptor {
    /**
     * @param proxy 代理对象
     * @param target 真实对象
     * @param method 方法
     * @param args 方法参数*/ 
    public boolean before(Object proxy, Object target, Method method,Object[] args);//判断是否满足创建真实对象的条件
    public void around(Object proxy, Object target, Method method,Object[] args);//false
    public void after(Object proxy, Object target, Method method,Object[] args);//true
}

定义一个拦截器实现类:

package Interceptor;

import java.lang.reflect.Method;

public class MyInterceptor implements Interceptor{
    @Override
    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("反射后");
    }
}

在JDK动态代理中使用拦截器:

package Interceptor;

import javax.xml.transform.Result;
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
     * @return 代理对象*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //判断拦截器
        if(interceptorClass == null){
            return method.invoke(target,args);
        }
        Object res = null;
        //通过反射生成拦截器
        Interceptor interceptor =(Interceptor)
                Class.forName(interceptorClass).newInstance();
        //前置方法
        if (interceptor.before(proxy,target,method,args)){
            //反射原有方法
            res = method.invoke(target,args);
        }else {
            //代理失败,around
            interceptor.around(proxy,target,method,args);
        }
        //代理生效,after
        interceptor.after(proxy,target,method,args);
        return res;
    }
}

测试

   public static void main(String[] args){
        HelloWorld proxy = (HelloWorld)
        InterceptorJdkProxy.bind(new HelloWorldImpl(),
                "Interceptor.MyInterceptor");
        proxy.say();
    }

SSM框架学习笔记day3---动态代理&拦截器_第3张图片
拦截器工作流程:SSM框架学习笔记day3---动态代理&拦截器_第4张图片

本博客大部分内容来自
[Java EE互联网轻量级整合开发SSM框架和Redis实现] --杨开阵,周吉文,梁华辉等.
中国公信出版社,电子工业出版社

你可能感兴趣的:(SSM+Redis实现)