第15章:Mybaties的Plugin插件功能实现

1.目标

本章节的目标就是用户在xml配置了类,我们需要实现在某处拦截执行用户配置的实现类,而这部分功能就是mybaties的插件扩展。

插件主要的设计理念就是依赖倒置,插件功能依赖于接口,而不是具体的实现,不依赖具体实现,在这个过程中对抽象进行编程,不对实现进行编程,这样就降低了客户与实现模块间的耦合。

而技术实现就需要用动态代理,我们需要用户配置被代理对象,被代理的方法以及参数,框架进行拦截操作,通过配置的方式把实现添加到Mybaties中(如图一),这样在执行插件代理方法invoke()时,就可以直接实现对应的实现类。看图二,用户注解的配置中,StatementHandler当作代理对象,方法是prepare,参数是Connection,那么当我们执行StatementHandler和其子类时并且方法是prepare的化就会执行代理invoke(),此时就会判断调度到用户的实现类里。

 

2.xml类图

看xml类图说明,

1.由XMLConfigBuilder开始进行解析插件内容,为什么从这里开始,因为我们的配置在mybatis-config-datasource.xml中(如下图),解析完毕将拦截器(用户实现)对象放入Configuration的拦截器链条中(InterceptorChain),

2.在执行对应Sql之前(newStatementHandler方法处),我们在此设置包装了代理方法,代理的是PreparedStatementHandler,是StatementHandler的子类,进入包装代理方法就会读取到用户实现类的注释,如Intercepts以及Signature注释得到被代理的类和方法以及参数,最后返回代理类。

3.此时StatementHandler已经被代理,所以执行prepare()时直接执行Plugin类下的incoke()方法,这时就执行用户的实现操作,用户操作完放行,这时继续执行框架里的操作。

3.代码 

3.1 xml插件解析

XMLConfigBuilder类里:此类添加了解析Plugin的方法,拿到了interceptor属性的插件实现类,以及对应的属性名称和值,最后将interceptor放入到拦截链条里(interceptorChain)

public class XMLConfigBuilder extends BaseBuilder {
     // 省略其他方法...

      public Configuration parse() {
        try {
            // 插件 step-16 添加
            pluginElement(root.element("plugins"));
            // 环境
            environmentsElement(root.element("environments"));
            // 解析映射器
            mapperElement(root.element("mappers"));
        } catch (Exception e) {
            throw new RuntimeException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
        return configuration;
    }

    // 解析插件
    private void pluginElement(Element parent) throws Exception {
        if (parent == null) return;
        List<Element> elements = parent.elements();
        for (Element element : elements) {
            String interceptor = element.attributeValue("interceptor");
            Properties properties = new Properties();
            List<Element> propertyElementList = element.elements("property");
            for (Element property : propertyElementList) {
                properties.setProperty(property.attributeValue("name"), property.attributeValue("value"));
            }
            // 获取插件实现类并实例化:cn.bugstack.mybatis.test.plugin.TestPlugin
            Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值