java 动态代理—— Mybaties 拦截器链基本原理实现
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 拦截器链基本原理实现的更多相关文章
- 【转载】由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理
转自:http://zhangbo-peipei-163-com.iteye.com/blog/2033832?utm_source=tuicool&utm_medium=referral 我 ...
- Mybatis使用动态代理实现拦截器功能
1.背景介绍 拦截器顾名思义为拦截某个功能的一个武器,在众多框架中均有“拦截器”.这个Plugin有什么用呢?或者说拦截器有什么用呢?可以想想拦截器是怎么实现的.Plugin用到了Java中很重要的一 ...
- 设计模式之jdk动态代理模式、责任链模式-java实现
设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...
- Java动态代理——框架中的应用场景和基本原理
前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...
- java动态代理基本原理及proxy源码分析一
本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的态度,于是对java动态代理的本质原理做了一些研究,于是便有了这个系列的文章 为了尽快进入正题,这里 ...
- java web 过滤器跟拦截器的区别和使用
注:文章整理自知乎大牛以及百度网友(电脑网络分类达人 吕明),特此感谢! 一.过滤器 1.什么是过滤器? 过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上.过滤器可附加到一个 ...
- JAVA 动态代理原理和实现
在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对 ...
- Spring异步调用原理及SpringAop拦截器链原理
一.Spring异步调用底层原理 开启异步调用只需一个注解@EnableAsync @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTI ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
随机推荐
- Jackson & fastJson的使用
Jackson import lombok.Data; @Data public class Student { private Long id; private String name; priva ...
- 动态sql & 抽取可重用sql
抽取可重用的sql片段 抽取:<sql id="xx"></sql> 使用:<include refid="xx">< ...
- 解决虚拟机安装linux系统无法全屏问题 & vmtools安装
修改设置 1) 如下图右单击虚拟机名,选择[settings-],调出虚拟机设置界面. 2) 在设置界面选择[hardware]->[CD/DVD2(IDE)]->[Connection] ...
- 暑假算法练习Day6
最近开始了实验室的生活,并且学习了bullet journal.希望接下来的每一天都能完成所有的任务. 1012 数字分类 (20 分) 给定一系列正整数,请按要求对数字进行分类,并输出以下 5 个数 ...
- [atARC110E]Shorten ABC
考虑令$a$.$b$和$c$分别对应1.2和3,那么每一次相当于令$x$和$y$变为$x\oplus y$(要求$x\ne y$) 根据异或的结合律,我们相当于将其划分为若干个区间求异或值 (另外还有 ...
- [luogu5537]系统设计
考虑哈希,令$h[x]$表示根到$x$路径的哈希值,那么有$h[x]+hash(l,r)=h[ans]$ 考虑用线段树维护$a_{i}$的区间哈希值,并用map去找到对应的$ans$ 但还有一个问题, ...
- Maven pom常用plugins配置说明
maven-compiler-plugin 编译Java源码,一般只需设置编译的jdk版本 <plugin> <groupId>org.apache.maven.plugins ...
- ThinkPad笔记本外放没声音解决办法(不是驱动的原因)
本人的本子是T480,自从装完Ubuntu系统之后W10系统就没有外放声音了,卸载Ubuntu之后还是没有声音,重装声卡驱动.重装系统之后依然无效. 我的解决办法是升级主板Bois,具体如下: 进入官 ...
- Spring Cloud Gateway过滤器精确控制异常返回(实战,完全定制返回body)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 Spring Cloud Gateway应用 ...
- 快速入门上手Markdown
第一次接触Markdown是写代码初期看很多大佬的github,他们的项目一定会有一份文件叫Readme.md的文件 他们由一些简单美观的符号和汉字字母组成,编译之后成为一篇简单直观的文档 深入了解之 ...