Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通过闭包和模式匹配实现Groovy的AOP?_Java_Regex_Groovy_Closures_Aop - Fatal编程技术网

Java 通过闭包和模式匹配实现Groovy的AOP?

Java 通过闭包和模式匹配实现Groovy的AOP?,java,regex,groovy,closures,aop,Java,Regex,Groovy,Closures,Aop,我有一个抽象的基本POGO: abstract class AuthorizingResource { void authorize(String credential) { if(!credentialIsValid(credential)) { throw new AuthorizationException(credential) } } boolean credentialIsValid(String cr

我有一个抽象的基本POGO:

abstract class AuthorizingResource {
    void authorize(String credential) {
        if(!credentialIsValid(credential)) {
            throw new AuthorizationException(credential)
        }
    }

    boolean credentialIsValid(String credential) {
        // Do stuff to determine yea or nay
    }
}
还有许多具体的子类,如:

class FizzResource extends AuthorizingResource {
    List<Fizz> getAllFizzes(String credential) {
        authorize(credential)

        List<Fizz> fizzes

        // Do stuff

        fizzes
    }

    Fizz getFizzById(String credential, Long id) {
        authorize(credential)

        Fizz fizz

        // Do stuff

        fizz
    }

    void considerTheLillies(Buzz buzz) {
        // Do stuff
    }

    void upsertFizz(String credential, Fizz fizz) {
        authorize(credential)

        // Do stuff
    }
}
class-FizzResource扩展了源代码{
列出getAllFizzes(字符串凭据){
授权(凭证)
列出汽水
//做事
气泡
}
Fizz getFizzById(字符串凭证,长id){
授权(凭证)
嘶嘶作响
//做事
起泡
}
无效的考虑因素(嗡嗡声){
//做事
}
无效向上插入嘶嘶声(字符串凭证,嘶嘶声){
授权(凭证)
//做事
}
}
正如你所看到的,有几件事正在发生:

  • 任何我想要验证/授权的
    FizzResource
    方法,我需要手动调用方法顶部的
    authorize(…)
  • 有些方法(
    considerillies
    )不需要进行身份验证
我想知道我是否可以通过使用一个闭包来模拟AOP,调用
authorize(…)
(这样我就不必一直无意识地添加它),它可以使用某种模式来选择在闭包中“包装”哪些方法。在
FizzResource
的特定情况下,这可能是其中包含“
*Fizz*
”的任何方法,但该模式(理想情况下)应该是任何有效的正则表达式不能更改的一件事是,任何接受
凭证的方法都不能修改其签名。

因此,基本上,类似于SpringAOP或GoogleGuice的方法拦截器,但使用本机Groovy闭包


有什么想法吗?

您可以将
invokeMethod
GroovyInterceptable
一起使用。请注意,名称中的任何
fizz
都将匹配:

abstract class AuthorizingResource implements GroovyInterceptable {
    def invoked = []
    def validator = [credentialIsValid : { true }]

    void authorize(String credential) {
        if ( !validator.credentialIsValid(credential) ) {
            throw new RuntimeException(credential)
        }
    }

    def invokeMethod(String method, args) {
        if (method.toLowerCase().contains('fizz')) {
            metaClass.getMetaMethod('authorize', String).invoke(this, args[0])
            invoked.add( 'authorized ' + method )
        }
        return metaClass
            .getMetaMethod(method, args*.getClass() as Class[])
            .invoke(this, args)
    }
}

class Fizz { String name }

class FizzResource extends AuthorizingResource {
    List<Fizz> getAllFizzes(String credential) { ['all fizzes'] }
    Fizz getFizzById(String credential, Long id) { new Fizz(name: 'john doe') }
    def considerTheLillies() { 42  }
}

res = new FizzResource()
assert res.getAllFizzes('cred') == ['all fizzes']
assert res.considerTheLillies() == 42
assert res.getFizzById('cred', 10l).name == 'john doe'

assert res.invoked == ['authorized getAllFizzes', 'authorized getFizzById']
抽象类AuthorizangResource实现GroovyInterceptable{
调用的定义=[]
def验证器=[credentialIsValid:{true}]
无效授权(字符串凭据){
如果(!validator.CredentialAlisValid(凭证)){
抛出新运行时异常(凭据)
}
}
def invokeMethod(字符串方法,args){
if(method.toLowerCase()包含('fizz')){
元类.getMetaMethod('authorize',String).invoke(这个,args[0])
add('authorized'+方法)
}
返回元类
.getMetaMethod(方法,args*.getClass()作为类[])
.invoke(此参数为args)
}
}
类Fizz{String name}
类FizzResource扩展了类源{
列出getAllFizzes(字符串凭据){['all fizzes']}
Fizz getFizzById(字符串凭证,长id){new Fizz(名称:'john doe')}
def considerthelliles(){42}
}
res=新的泡沫资源()
assert res.getAllFizzes('cred')=['all fizzes']
assert res.considerthelliles()==42
assert res.getFizzById('cred',10l)。name=='john doe'
assert res.invoked==['authorized getAllFizzes','authorized getFizzById']

我无法停止思考基于闭包的解决方案。我提出了一些Javascript风格的代码,使用闭包和映射。它没有继承性:

class AuthorizingResource {
    void authorize(String credential) {
        if(!credentialIsValid(credential)) {
            throw new RuntimeException(credential)
        }
    }
    boolean credentialIsValid(String credential) { true }
}

class Fizz {}

abstract class FizzResource {
    abstract List<Fizz> getAllFizzes(String credential)
    abstract int getFizzById(String credential, Long id)
    abstract void considerTheLillies(buzz)

    static createFizzResource(authorized) {
        def auth = new AuthorizingResource()
        def authorize = { auth.authorize it; authorized << it }

        return [ 
            getAllFizzes       : { String credential -> ['fizz list'] },
            getFizzById        : { String credential, Long id -> 42 },
            considerTheLillies : { buzz -> }
        ]
        .collectEntries { entry ->
            entry.key.toLowerCase().contains('fizz') ? 
                [(entry.key) : { Object[] args -> 
                    authorize(args[0]); entry.value(*args) 
                }] : 
                entry
        } as FizzResource

    }
}

注意
authorized
列表非常愚蠢,仅用于
assert
目的。

您是否尝试过使用
invokeMethod
拦截方法调用并在适用的情况下调用
authorize
?以下是一个示例答案:
def authorized = []

def fizz = FizzResource.createFizzResource(authorized)
assert authorized == []
assert fizz.getAllFizzes('getAllFizzes cred') == ['fizz list']

fizz.considerTheLillies null
assert authorized == ['getAllFizzes cred']

assert fizz.getFizzById('fizz by id cred', 90l) == 42
assert authorized == ['getAllFizzes cred', 'fizz by id cred']