Java 通过闭包和模式匹配实现Groovy的AOP?
我有一个抽象的基本POGO: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
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
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']