我写了一个用junit测试的方面。这个方面在一个名为setQuery
的第三方方法上有一个@Around建议。在编译时,它会抱怨:Can't find referenced pointcut setQuery
这是我的一面:
@Component
@Aspect
public class ElasticsearchQuerySecurityAspect {
@Around("org.elasticsearch.action.search.SearchRequestBuilder.setQuery() && args(queryBuilder)")
public void addFilter(final ProceedingJoinPoint pjp, QueryBuilder queryBuilder) throws Throwable {
Object[] args = pjp.getArgs();
// Set the filter to use our plugin
FilterBuilder securityFilter = FilterBuilders.scriptFilter("visibility-filter")
.lang("native")
.addParam("visibility-field", "visibility")
.addParam("parameter", "default");
// Re-create original query with the filter applied
QueryBuilder newQuery = QueryBuilders.filteredQuery(queryBuilder,securityFilter);
log.info("Adding filter to search request");
// Tell the method to run with the modified parameter
args[0] = newQuery;
pjp.proceed(args);
}
}
这是我的junit测试:
@RunWith(SpringJUnit4ClassRunner.class)// NOTE #1
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@EnableLoadTimeWeaving
@ComponentScan
public class ElasticsearchQuerySecurityTest {
Client client = mock(Client.class);
@Before
public void setUp() throws Exception {
}
@Test
public void test() {
SearchRequestBuilder s = new SearchRequestBuilder(client);
QueryBuilder qb = QueryBuilders.queryString("name:foo");
XContentBuilder builder;
try {
builder = XContentFactory.jsonBuilder();
qb.toXContent(builder, null);
assertEquals("{\"query_string\":{\"query\":\"name:foo\"}}",builder.string());
// Call setQuery() which will invoke the security advice and add a filter to the query
s.setQuery(qb);
builder = XContentFactory.jsonBuilder().startObject();
qb.toXContent(builder, null);
builder.endObject();
assertEquals("{\"query\": "+
"{ \"filtered\": "+
"{ \"query\": "+
"{ \"query_string\": "+
"{ \"name:foo\", } }, "+
"\"filter\": "+
"{ \"script\": "+
"{ \"script\": \"visibility-filter\","+
"\"lang\":\"native\", "+
"\"params\": "+
"{ \"visibility-field\":\"visibility\", "+
"\"parameter\":\"default\" } } } } } }",
builder.string());
} catch (IOException e) {
fail("We threw an I/O exception!");
}
}
}
我在类路径上也有这个aop.xml:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<include within="org.elasticsearch.action.search.*"/>
</weaver>
<aspects>
<aspect name="org.omaas.security.ElasticsearchQuerySecurityAspect"/>
</aspects>
</aspectj>
我尝试了@Around("execution(public * set*())")
的一个方面,发现它只建议当前包中的内容。我怎样才能把它应用到第三方包里的东西上?
发布于 2014-09-25 09:23:25
春天的AOP只能编织成春豆。由于第三方目标类不是Spring,因此无法对其应用方面。为此,您需要使用AspectJ,它功能更强大,不依赖基于动态代理的Spring的“AspectJ”实现。
对于AspectJ,您有两个选项:
编辑:哦,顺便说一下,切入点语法是无效的。你不能写
@Around("org.elasticsearch.action.search.SearchRequestBuilder.setQuery() && args(queryBuilder)")
相反,你更需要这样的东西
@Around("execution(* org.elasticsearch.action.search.SearchRequestBuilder.setQuery(*)) && args(queryBuilder)")
一个方法名称是不够的,您必须告诉AOP框架您想要捕获它的execution()
(在AspectJ中,cou也可以通过call()
捕获其所有调用者)。其次,您将不会通过指定没有任何参数的方法签名setQuery()
来捕获具有一个setQuery()
参数的方法,因此,我建议您使用setQuery(*)
,或者,如果您想更精确地使用setQuery(org.elasticsearch.index.query.QueryBuilder)
。您还需要一个返回类型和/或修饰符,比如方法名前面的public
,或者像*
这样的joker。
https://stackoverflow.com/questions/25894767
复制相似问题