使用Groovy的mixin方法注入,和mixedIn属性实现过滤链 mixin方法注入不多说,这里只是用这个属性搞一个过滤器链的功能

假设我现在有个方法,输入一个字符串,然后需求提出需要进行大写转换输出,

过了一天又要加个前缀,再过了一天,需要把一些字符过滤掉......一直修改代码肯定是最low的,所以可以利用mixedIn属性,

设计一个过滤链,加需求,只需要新增一个过滤器就行了!

目标实例:

class StringWriter extends MyWriter {
    @Override
    void write(String message) {
        println message
    }
}

  主要实现字符串打印

注入的过滤器,我这里只设计两个:

转大写:

class UpperCaseFilter {
    void write(String message){
        def upperCase = message.toUpperCase()
        //将转换后的消息传递给下一个mixin链条
        def clazz = this.getClass()
        //遍历mixin的链表,找到当前mixin的前一个
        /**
         * mixedIn: groovy提供的一个属性,为实例保存有序的mixin注入类链表
         */
        for(mixin in mixedIn.mixinClasses){
            //会按添加顺序从前往后开始遍历,如果实例不是当前实例,那么就继续
            //直到找到当前实例时,执行的clazz是前一个mixin,最后一个mixin的是目标实例
            if(mixin.mixinClass.theClass==metaClass.delegate.theClass) break
            clazz=mixin.mixinClass.theClass  //一直赋值,break时,clazz刚好是当前实例的前一个
        }
        //如果当前实例在mixin中,执行当前实例方法,否则执行目标实例方法
        mixedIn[clazz].write(upperCase)
    }
}

  

加前缀:

class PrefixFilter {

    void write(String message){
        message="prefix-----:"+message
        def clazz = this.getClass()
        //遍历mixin的链表,找到当前mixin的前一个
        for(mixin in mixedIn.mixinClasses){
            if(mixin.mixinClass.theClass==metaClass.delegate.theClass) break
            clazz=mixin.mixinClass.theClass
        }
        mixedIn[clazz].write(message)
    }
}

  可以把遍历调用这块抽取出来或者注入到object更好,我这里懒就不弄了,主要是熟悉这个设计

方法测试:

def sendMessage(MyWriter write){
    write.write("this is groovy")
}
//创建添加过滤器的writer实例
def creeateInstance(MyWriter writer,Object[] filters =[]){
    //将过滤器注入到writer实例的mixin中
    filters.each {filter-> writer.metaClass.mixin filter}
    writer
}
//当注入多个同名同参方法时,最后加入mixin中的方法会自动隐藏掉前面的方法
// 所以默认前面的不会执行,只会执行最后一个
/**
 * 这里需要按照需求控制顺序,因为过滤器会按照顺序严格执行,比如,是先加前缀还是先转大写
 */
sendMessage(creeateInstance(new StringWriter(),PrefixFilter,UpperCaseFilter))
sendMessage(creeateInstance(new StringWriter(),UpperCaseFilter,PrefixFilter))

  结果,顺序不同,结果不同:

使用Groovy的mixin方法注入,和mixedIn属性实现过滤链
mixin方法注入不多说,这里只是用这个属性搞一个过滤器链的功能

加需要的时候,只需要加个filter注入到StringWriter中就可以了!!!