一、拦截器的理解

  学习拦截器之前需要对动态代理和反射有一定的基础。

  官方说法:

          java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。 

简单来说,就是拦截器可以提供一个在方法调用之前的方法,调用之后的方法,方便我们在方法执行的前后做拦截判或其他业务处理。

二、Jdk动态代理+拦截器

创建一个普通接口:HelloWorld.java

 package com.xfwl.proxy.jdk;

 public interface HelloWorld {
public void sayHelloWorld();
}

创建一个上面皆接口的实现子类:HelloWorldImpl.java

 package com.xfwl.proxy.jdk;

 public class HelloWorldImpl implements HelloWorld {

     public void sayHelloWorld() {
System.out.println("Hello World!");
}
}

创建一个拦截器的接口:Interceptor.java

package com.xfwl.interceptor;

import java.lang.reflect.Method;

/**
* 定义一个拦截器接口
* @function
* @author 小风微凉
* @time 2018-7-9 下午2:20:35
*/
public interface Interceptor {
/**
* 拦截器-真实方法调用之前before
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
* @return 返回boolean false则执行around(),true则不执行around()
*/
public boolean before(Object proxy,Object target,Method method,Object[] args);
/**
* before()返回 false则执行around(),true则不执行around()
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
*/
public void around(Object proxy,Object target,Method method,Object[] args);
/**
* before/around执行之后执行after()
* @param proxy 代理对象
* @param target 真实对象
* @param method 真实方法
* @param args 运行参数
*/
public void after(Object proxy,Object target,Method method,Object[] args);
}

创建上面拦截器接口的实现子类:MyInterceptor.java

 package com.xfwl.interceptor;

 import java.lang.reflect.Method;
/**
* 拦截器实现子类
* @function 理解拦截器之前需要理解动态代理+反射机制
* @author 小风微凉
* @time 2018-7-9 下午2:25:34
*/
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("反射方法后逻辑!");
}
}

创建一个动态代理类:InterceptorJdkProxy.java

 package com.xfwl.interceptor;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK动态代理实现类
* @function 在代理类中嵌入拦截器,关键点还是动态代理
* @author 小风微凉
* @time 2018-7-9 下午2:29:21
*/
public class InterceptorJdkProxy implements InvocationHandler {
//真实对象
private Object target=null;
//拦截器全称
private String interceptorClass=null;
//动态代理类构造器
public InterceptorJdkProxy(){}
public InterceptorJdkProxy(Object target,String interceptorClass){
this.interceptorClass=interceptorClass;
this.target=target;
}
/**
* 给真实独享绑定代理对象
* @param target 真实对象
* @param interceptorClass 拦截器的全称
* @return 代理对象【占位】
*/
public Object bind(Object target,String interceptorClass){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),//真实对象的类加载器
target.getClass().getInterfaces(), //真实对象的实现接口
new InterceptorJdkProxy(target, interceptorClass)//实现了InvocationHandler接口的实现类,一般为当前代理类对象
);
}
/**
* 通过代理对象调用方法,首先进入这个方法
* @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(this.target, args);
}
Object result=null;
//通过反射拿到拦截器对象
Interceptor interceptor =(Interceptor)Class.forName(interceptorClass).newInstance();
//调用前置方法
if(interceptor.before(proxy, args, method, args)){
//反射真实对象原有的方法
result=method.invoke(target, args);
}else{
//返回false,执行around方法
interceptor.around(proxy, args, method, args);
}
//调用后置方法
interceptor.after(proxy, args, method, args);
return result;
}
}

创建一个测试类:TestInterceptor.java.

 package com.xfwl.interceptor;

 import com.xfwl.proxy.jdk.HelloWorld;
import com.xfwl.proxy.jdk.HelloWorldImpl; /**
* 拦截器测试
* @function 测试一下拦截器是如何起作用的,
* @author 小风微凉
* @time 2018-7-9 下午2:19:15
*/
public class TestInterceptor { /**
* @param args
*/
public static void main(String[] args) {
//拿到代理对象,并绑定真实对象
HelloWorld proxy=(HelloWorld) new InterceptorJdkProxy().bind(
new HelloWorldImpl(),
"com.xfwl.interceptor.MyInterceptor"
);
//执行代理逻辑
proxy.sayHelloWorld(); } }

测试结果:

运行条件【1】:

 @Override
public boolean before(Object proxy, Object target, Method method,Object[] args) {
System.out.println("反射方法前逻辑!");
return false;
}

运行结果:

反射方法前逻辑!
取代了被代理对象的方法!
反射方法后逻辑!

运行条件【2】:

 @Override
public boolean before(Object proxy, Object target, Method method,Object[] args) {
System.out.println("反射方法前逻辑!");
return true;
}

运行结果:

反射方法前逻辑!
Hello World!
反射方法后逻辑!

从上面可以看出,拦截器生效了!

JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(4):JDK动态代理+拦截器的更多相关文章

  1. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(2):SSM+Redis概念理解

    一.SSM+Redis的结构图 在Java互联网中,以Spring+SpringMVC+MyBatis(SSM)作为主流框架,SSM+Redis的结构图如下: 二.下面介绍它们各自承担的功能: 1.S ...

  2. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(1):Mybatis和Hibernate概念理解

    一.关键字说明: oop:面向对象 aop:面向切面 ioc:控制反转 orm:对象关系映射 pojo:数据库表映射的java实体类 二.常识说明:1.hibernate和mybatis都属于持久层. ...

  3. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(12):XML配置自动扫描包,自动加载*.properties文件

    一.XML和注解组合使用 前几篇的测试案例都是在Java类中配置,现在换一种使用方式,在XML中配置,使Spring IoC容器在启动之后自动去扫描配置的包路径,扫描加载指定路径下的propertie ...

  4. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(10):通过注解(annotation)装配Bean之(@Configguration、@Component、@Value、@ComponentScan、@Autowired、@Primary、@Qualifier、@Bean)

    一.通过注解(annotation)装配Bean 通过之前的学习,我们已经知道如何使用XML装配Bean,但是更多的时候已经不再推荐使用XML的方式去装配Bean,更多的时候会考虑注解(annotat ...

  5. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(8):装配SpringBean概述(如何合理使用装配级别)

    一. 装配Bean概述  关于如何将自己开发的Bean配置到Spring IoC容器中,大部分场景下,我们都会使用ApplicationContext的具体实现类,因为对应的Spring IoC容器功 ...

  6. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(7):装配SpringBean·依赖注入装配

    一.依赖注入的三种方式      在实际环境中实现IoC容器的方式主要分为两大类,一类是依赖查找,依赖查找是通过资源定位,把对应的资源查找回来.另一类则是依赖注入.一般而言,依赖注入可分为3中方式: ...

  7. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(6):Spring IOC容器学习(概念、作用、Bean生命周期)

    一.IOC控制反转概念 控制反转(IOC)是一种通过描述(在Java中可以是XML或者是注解)并通过第三方去生产或获取特定对象的方式. 主动创建模式,责任在于开发者,而在被动模式下,责任归于Ioc容器 ...

  8. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(11):XML和Annotation装配Bean的混合使用(@ImportResource)

    一.XML和Annotation装配Bean如何合理使用 引入第三方资源包中类的时候,建议使用XML配置,而使用自己编写的Java类的时候,推荐使用Annotation注解配置Bean. 二.关于注解 ...

  9. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(9):通过XML装配Bean

    一.通过XML装配Bean 装配简易值 装配集合 命名空间装配(暂不测试) 二.测试例子 创建一个用户类:UserBean.java package com.xfwl.spring.assem; /* ...

  10. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(5):责任链模式、观察者模式

    一.责任链模式.观察者模式 1.责任链模式:当一个对象在一条链上被多个拦截器处理(烂机器也可以选择不拦截处理它)时,我们把这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景.   2. ...

随机推荐

  1. cors,跨域资源共享,Java配置

    一.概念 1. 如果两个页面的协议.域名和端口是完全相同的,那么它们就是同源的,不同则为跨域 2. ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允 ...

  2. 【转】Jmeter + DadBoby 安装使用

    一直接触LR比较多,这阵子突然想了解一下开源的性能测试工具,无意中接触到了Jmeter+Badboy,这两款工具对于想进行性能测试,但又对LR高额的商业费用望而止步的小公司可谓是再适合不过了. 自已小 ...

  3. 杂项-EMS:目录

    ylbtech-杂项-EMS:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   ...

  4. CentOS7 日期时间设置

    1.设置系统时间为中国时区并启用NTP同步 yum install ntp //安装ntp服务 systemctl enable ntpd //开机启动服务 systemctl start ntpd ...

  5. mybatis如何防止sql注入(2)

    Mybatis框架下SQL注入漏洞修复建议1. 模糊查询like SQL注入修复建议按照新闻标题对新闻进行模糊查询,可将SQL查询语句设计如下:select * from news where ti ...

  6. Dev TreeList基本用法

    public partial class treelist_shijian : DevExpress.XtraEditors.XtraForm      {          public treel ...

  7. JavaScript语言基础-基本数据类型与对象类型

  8. DDD学习笔录——提炼问题域之有效提炼知识的模型(三)

    方式六:延迟对模型中概念的命名 对领域建模时命名很重要. 因为在不断的知识提炼过程中经常会发现已经被命名的概念与你最初理解的有出入,这时你当初的命名就会变成一个问题.其问题在于  最初选作名称的这个词 ...

  9. 微信公众号php从0开发,包括功能(自定义菜单,分享)

    之前写的一篇微信公众号文章. 工作需要,进行此次调研,并记录开发过程. 开发目的,页面授权,页面获取用户头像,用户昵称 微信id, 分享页面. 微信订阅号 无法获取用户个人信息 写在记录前,公众号也是 ...

  10. Linux下zip格式文件的解压缩和压缩

    Linux下zip格式文件的解压缩和压缩 Linux下的软件包很多都是压缩包,软件的安装就是解压缩对应的压缩包.所以,就需要熟练使用常用的压缩命令和解压缩命令.最常用的压缩格式有.tar.gz/tgz ...