1.摘要

  Mybaties 中有个分页插件,之前有特意的去了解了一下原理 :https://www.cnblogs.com/jonrain0625/p/11168247.html,从了解中得知分页插件是基于Mybaties的拦截器去实现的,这个插件就是一个拦截器,和别的拦截器组成了Mybaties的拦截器链,然后所有的拦截器都对Executor 这个类 做了动态代理。本次主要的再次去学习下这个动态代理,去实现一个最基本的拦截器链的效果。当然还有spring aop 等很多地方都是基于动态代理去实现的,关于Aop可以在 :https://www.cnblogs.com/lcngu/p/5339555.html 去了解。本次也是基于这篇文章,及代码去学习和实现 拦截器链。

2.java动态代理

  java中代理模式分静态代理和动态代理,而动态代理的实现有两种实现方法,一种是基于JDK 用 接口方法去实现 ,一种是基于CGLIB 基于类去实现 ,了解可以看:https://www.cnblogs.com/rinack/p/7742682.html 。

  2.1 JDK 代理的基本使用:

    1.创建代理类的接口

    2.实现代理类执行的接口 InvocationHandler

    3.生成代理对象:Proxy.newProxyInstance(loader, interfaces, h);

    4.使用代理对象

    

3.示列  

  示列实现对user类的log方法拦截 ,在执行log方法之前,拦截器链中 LogIntercept1 和LogIntercept2 对log 方法拦截 ,做业务逻辑,拦截器链优点的很好体现是,实现耦合,可以高度的做到对内修改 。

  3.1  新建代理类接口 和代理类

  

public interface Log {
public void log();
}

 

public class User  implements Log{
String name = "user1";
public void log() {
System.out.println("user1 ----- 登陆");
}
}

  3.2  新建 InvocationHandler 的实现类

    为了封装 , 在bin方法中调用 Proxy.newProxyInstance 创建代理对象 ,把代理对象  和拦截器注入到代理对象,在 invoke方法中用拦截器代理执行。

  

public class Handler implements InvocationHandler{
//调用对象
private Object proxy;
//目标对象
private Intercept intercept; private Handler(Intercept target,Object proxy) {
this.intercept=target;
this.proxy=proxy;
}
public static Object bind(Intercept target,Object proxy){
return Proxy.newProxyInstance(
proxy.getClass().getClassLoader()
, proxy.getClass().getInterfaces(), new Handler(target,proxy));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return intercept.intercept(this.proxy,method,args);
}
}

 3.3 创建拦截器

    拦截器和拦截器的实现,偷懒写在一个文件中

  

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public interface Intercept {
Object intercept(Object o, Method m, Object[] os );
}
class LogIntercept1 implements Intercept { @Override
public Object intercept(Object o, Method m, Object[] os) {
try {
System.out.println("LogIntercept1 拦截登陆操作 做相关业务逻辑");
return m.invoke(o,os);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
} }
class LogIntercept2 implements Intercept { @Override
public Object intercept(Object o, Method m, Object[] os) {
try {
System.out.println("LogIntercept2 拦截登陆操作,做相关业务逻辑");
return m.invoke(o,os);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
}
}

 3.4 创建一个代理工厂

    在类中根据拦截器的数量,对代理类做循环。每次代理都把拦截器传入代理对象中 。

  

package 设计模式.com.pox.logPoxy;

import java.util.ArrayList;
import java.util.List; public class ProxyFactory { List<Intercept> InterceptChain = new ArrayList<Intercept>() {
private static final long serialVersionUID = 1L; {
add(new LogIntercept1());
add(new LogIntercept2());
}
}; public Object proxy(Class<?> classz) throws Exception {
try {
Object obj = classz.newInstance();
return InterceptAll(obj);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("代理异常");//抛出个异常,不另外设计异常类了,用RuntimeException 代替
}
} /** 拦截器代理
* @param obj
* @return
*/
private Object InterceptAll(Object obj) {
if(InterceptChain.isEmpty()) {
return obj;
}
for (Intercept intercept : InterceptChain) {
obj = Handler.bind(intercept,obj);
}
return obj;
} // 一下是单列的创建模式
public ProxyFactory(){
if(inner.proxyFactory != null) {
throw new RuntimeException("不允许创建多个实例");
}
}
public static ProxyFactory getProxyFactory() {
return inner.proxyFactory;
}
private static class inner{
static ProxyFactory proxyFactory = new ProxyFactory();
}
}

  3.5 测试

public class Test {
public static void main(String[] args) throws Exception {
ProxyFactory proxyFactory = ProxyFactory.getProxyFactory();
Log user = (Log) proxyFactory.proxy(User.class);
user.log();
}
}
/**
ouput :
LogIntercept2 拦截登陆操作
LogIntercept1 拦截登陆操作
user1 ----- 登陆
*/

以上就是一个简单的拦截器链实现,可以去查阅Mybaties的拦截器链,其原理是一样的,如果业务需要增加个拦截器链,实现接口 Intercept ,添加到代理工厂 ProxyFactory 拦截器链 InterceptChain中即可,实现高度的解耦功能。

java 动态代理—— Mybaties 拦截器链基本原理实现的更多相关文章

  1. 【转载】由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理

    转自:http://zhangbo-peipei-163-com.iteye.com/blog/2033832?utm_source=tuicool&utm_medium=referral 我 ...

  2. Mybatis使用动态代理实现拦截器功能

    1.背景介绍 拦截器顾名思义为拦截某个功能的一个武器,在众多框架中均有“拦截器”.这个Plugin有什么用呢?或者说拦截器有什么用呢?可以想想拦截器是怎么实现的.Plugin用到了Java中很重要的一 ...

  3. 设计模式之jdk动态代理模式、责任链模式-java实现

    设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...

  4. Java动态代理——框架中的应用场景和基本原理

    前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...

  5. java动态代理基本原理及proxy源码分析一

    本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的态度,于是对java动态代理的本质原理做了一些研究,于是便有了这个系列的文章 为了尽快进入正题,这里 ...

  6. java web 过滤器跟拦截器的区别和使用

    注:文章整理自知乎大牛以及百度网友(电脑网络分类达人 吕明),特此感谢! 一.过滤器 1.什么是过滤器? 过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上.过滤器可附加到一个 ...

  7. JAVA 动态代理原理和实现

    在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对 ...

  8. Spring异步调用原理及SpringAop拦截器链原理

    一.Spring异步调用底层原理 开启异步调用只需一个注解@EnableAsync @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTI ...

  9. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

随机推荐

  1. 谷粒 | 11 | nginx windows版简单安装使用

    nginx配置 下载安装 传送门:官网下载 官网提供三种版本: Mainline version:Mainline 是 Nginx 目前主力在做的版本,可以说是开发版 Stable version:最 ...

  2. 为什么建议使用你 LocalDateTime ,而不是 Date?

    在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗 通过阅读本篇文章你将了解到: 为什么需要LocalDate.Loca ...

  3. Django笔记&教程 6-4 forms进阶操作,重写forms方法

    Django 自学笔记兼学习教程第6章第4节--forms进阶操作,重写forms方法 点击查看教程总目录 1 - 重写clean方法 在本章第三节中,我们举了个注册学生账号的例子,里面我们使用模型来 ...

  4. 菜鸡的Java笔记第三 - java 自动转换原则

    自动转换原则 数据范围保存大的数据类型要转换为数据范围保存小的数据类型,使用强制转换(强制转型就是在变量的前面加括号,在括号里写上需要强制要转的类型.) 数据范围保存小的数据类型可以自动转换为数据范围 ...

  5. [年薪60W分水岭]基于Netty手写Apache Dubbo(带注册中心和注解)

    阅读这篇文章之前,建议先阅读和这篇文章关联的内容. 1. 详细剖析分布式微服务架构下网络通信的底层实现原理(图解) 2. (年薪60W的技巧)工作了5年,你真的理解Netty以及为什么要用吗?(深度干 ...

  6. Maven 依赖调解源码解析(七):总结

    本文是系列文章<Maven 源码解析:依赖调解是如何实现的?>第七篇,也是最后一篇,主要做个总结.请按顺序阅读其他系列文章,系列文章总目录参见:hhttps://www.cnblogs.c ...

  7. Springboot 加载配置文件源码分析

    Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...

  8. [atAGC054D]ox

    对于两个字符串$s$和$t$(保证其中每一种字符个数相同),定义$s$和$t$的相对逆序对数为$s$得到$t$的最少交换次数,显然同种字符相对顺序保持不变,因此即依次编号后的逆序对数 问题不妨看作构造 ...

  9. flutter第一课

    网上搜到有一个8小时体验flutter的教程,感觉可以尝试一个hello world出来:https://www.jianshu.com/p/9aaabc60d8af 官网下载很慢,可以使用镜像下载, ...

  10. 2017年最有前景的十大IT职业岗位

    在IT行业,并不常存在失业的现象,因为目前整个行业存在严重的专业人才供给不足的现象:但同样,想要进入这个行业并牢牢站稳脚跟,你也需要拥有更强于其他行业的竞争力和承受更大的压力.那在行业中,哪些职位更有 ...