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中即可,实现高度的解耦功能。

原文地址:https://www.cnblogs.com/jonrain0625/p/11431511.html

时间: 2024-10-12 15:40:23

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

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

最近在用mybatis做项目,需要用到mybatis的拦截器功能,就顺便把mybatis的拦截器源码大致的看了一遍,为了温故而知新,在此就按照自己的理解由浅入深的理解一下它的设计. 和大家分享一下,不足和谬误之处欢迎交流.直接入正题. 首先,先不管mybatis的源码是怎么设计的,先假设一下自己要做一个拦截器应该怎么做.拦截器的实现都是基于代理的设计模式设计的,简单的说就是要创造一个目标类的代理类,在代理类中执行目标类的方法并拦截执行拦截器代码. 那么我们就用JDK的动态代理设计一个简单的拦截器

动态代理和拦截器

一.概述 1.代理模式是常用的java设计模式,生成一个代理对象,来代替真正的对象,从而控制真实对象的访问.       客户(调用者)----------商务(代理对象)-----------软件工程师(真正对象) 2.我们需要在调用者调用对象之前就生成一个代理对象,而这个代理对象需要和真正对象建立代理关系 -----代理对象和真正对象建立关系 -----实现代理对象的代理逻辑方法 3.常用的代理对象方法:JDK动态代理,CGLIB 二.JDK动态代理   JDK动态代理所用到的代理类在程序调

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

1.首先要明确什么是拦截器.什么是过滤器 1.1 什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作.拦截是AOP的一种实现策略. 在Webwork的中文文档的解释为--拦截器是动态拦截Action调用的对象.它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也是提供了一种可以提取action中可重用的部分的方式.

JAVA 动态代理原理和实现

在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对象会拦截对被代理对象的方法调用,在其中可以全然抛弃被代理对象的方法实现而完成另外的功能,也可以在被代理对象方法调用的前后增加一些额外的功能. 动态代理可以为其他对象提供一个代理以控制对某个对象的访问. 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. JDK

java动态代理【一】

java动态代理的定义:为其他目标类的方法增加切面的逻辑,即在执行目标类方法的时候,先去执行一段如校验检测的逻辑代码.java通俗一点就是生成一个继承目标类的子类,并在每个调用方法都添加一段逻辑. 应用场景:当我们从别的项目迁移过来的代码进行修改的时候,如果有一个需求是当要执行某个业务类的所有方法前,需要校验其权限或其他的时候,如果这个类是源代码,我们还可以在类的基础上对每个方法区更改,但若是打包成jar包的类,若该类有接口还可以实现一个代理模式创建一个代理类,没有接口就比较麻烦,但接口一旦多起

spring---aop(3)---Spring AOP的拦截器链

写在前面 时间断断续续,这次写一点关于spring aop拦截器链的记载.至于如何获取spring的拦截器,前一篇博客已经写的很清楚(spring---aop(2)---Spring AOP的JDK动态代理) 获取拦截器链 final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { public Object invoke(Object proxy, Method method, Ob

java?动态代理范例?InvocationHandler与Proxy

java 动态代理范例 InvocationHandler与Proxy,拦截与代理 java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序(详见api文档) java.lang.reflect.InvocationHandler,InvocationHandler 是代理实例的调用处理程序 实现的接口.invoke()在代理实例上处理方法调用

Java动态代理--&gt;Spring AOP

引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Java基础知识,希望对大家有所帮助.): [1] Java反射知识-->Spring IoC :http://www.iteye.com/topic/1123081 [2] Java动态代理-->Spring AOP :http://www.iteye.com/topic/1123293 [3] 属性

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕