我想在Jersey控制器上创建一个Aspect来衡量服务执行的时间。我正在与我的切入点作斗争,因为它没有被检测到,我的方面永远不会被启动。
我尝试过使用许多切入点,例如:
execution(@Monitor * *.*(..))
execution(public * *(..))
change the order of @Aspect and @Component
Added a pointcut like this:
@Pointcut("execution(@Monitor * *.*(..))")
public void monitorRequestTargets(){}
@Around("monitorRequestTargets()")
Tried using AOP and CGLIB
<aop:aspectj-autoproxy proxy-target-class="true"/>
Also tried changing the order of configuration in context.xml
Eclipse检测到我的方法正在建议我的方法,但它不会在运行时执行。你能否给我一些提示,说明为什么没有创建方面或切入点没有启动?
我的代码如下。
context.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- Enables the Spring MVC @Controller -->
<annotation-driven />
<!-- Enables AspectJ -->
<aop:aspectj-autoproxy />
<!-- .....more definitions -->
<context:component-scan base-package="com.mypackage" />
</beans:beans>
我的 MonitorAspect
@Component
@Aspect
public class MonitorAspect
{
private static final Logger logger = LoggerFactory.getLogger(MonitorAspect.class);
@Around("@annotation(com.mypackage.Monitor)")
public void logTimeUsage(ProceedingJoinPoint joinPoint) throws Throwable
{
// Store executing method
String method = joinPoint.getSignature().getName();
// Track time
long startTime = System.currentTimeMillis();
joinPoint.proceed();
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
// Log time consumed by executing method
logger.info(method + ": " + duration);
}
}
My Monitor自定义注释
@Target(value = {ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor
{
}
我想使用方面的控制器:
@Monitor
@POST
@Consumes("application/json")
@Produces("application/json")
@Path("/{tkn}/test/")
public Response test(
@Context HttpServletRequest httpReq,
@Context UriInfo uri,
String enrollReqJson
) {
Thread.sleep(1000); // Implementation is not important
}
我的 pom.xml
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Jersey / Spring -->
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.14</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.8</version>
</dependency>
<!-- Spring AOP / AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
答案 0 :(得分:3)
看起来我遇到了同样的问题。根据您提供的内容,看起来您在Spring上创建的对象上使用Spring AOP(可能是Jersey是创建控制器类实例的对象),因此建议未应用。 Eclipse说它被建议,但这只适用于由Spring创建的控制器实例。您实际使用的是Jersey(或您正在使用的任何提供商)创建的那些,不建议使用。
我花了很多时间试图让Jersey使用Spring来创建控制器实例(包括一些声称能够做到这一点的插件),但从来没有让它工作。我能够直接使用AspectJ而不是Spring AOP来实现它。这不是很难,除了弄清楚如何让春天注入这个方面。
添加了:
注释保持不变。您只需要从spring.xml中删除AOP内容,并在META-INF中创建一个aop.xml文件。这就是我的样子:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<aspects>
<aspect name="com.ancestry.academy.api.ServiceApiAspect" />
<aspect name="com.ancestry.academy.manager.ManagerApiAspect" />
</aspects>
</aspectj>
您可以将Spring AOP保留为弹簧加载的类。您只需要为在spring之外创建的类(如jax的控制器)执行此操作。
我真的不懂一点黑魔法。如果你需要使用spring注入你自己的方面,那么你需要在spring.xml中声明它,如下所示:
<bean id="serviceApiAspect" class="com.ancestry.academy.api.ServiceApiAspect" factory-method="aspectOf" />
<bean id="managerApiAspect" class="com.ancestry.academy.manager.ManagerApiAspect" factory-method="aspectOf" />
请注意,我的方面没有名为aspectOf的方法。显然是由AspectJ添加的。这就是它的全部内容。
答案 1 :(得分:0)
添加
compile 'org.aspectj:aspectjtools:1.8.1'
compile 'org.aspectj:aspectjrt:1.8.1'
制作注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ParmsAudit
{
String action();
}
方面类
@Aspect
public class AuditAspect {
@Before(value="execution(@uk.co.billcomer.audit.ParmsAudit * *(..)) && @annotation(parmsAudit)", argNames="parmsAudit")
public void logTheAuditActivity(JoinPoint aPoint, ParmsAudit parmsAudit) {
String userName = getUserName();
mlogger.info("Parms Auditing User Name: " + userName);
mlogger.info("auditType:" + parmsAudit.auditType().getDescription());
String arguments = getArgs(aPoint.getArgs());
if (arguments.length() > 0) {
mlogger.info("args-" + arguments);
}
}
private String getArgs(Object[] args) {
String arguments = "";
int argCount = 0;
for (Object object : args) {
if (argCount > 0) {
arguments += ", ";
}
arguments += "arg[" + ++argCount + "]=" + "[" + object + "]";
}
return arguments;
}
private String getUserName() {
try {
return SecurityContextHolder.getContext().getAuthentication().getName();
} catch (NullPointerException npe) {
return "Unknown User";
}
}
}
这是很好的链接http://billcomer.blogspot.in/2011/07/auditing-using-aop-and-annotations-in.html