我正在尝试使用AOP做SQL查询分析
下面是@Aspect definition
的代码片段@Pointcut("(call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..)))")
public void profileQuery() {
}
@Around("profileQuery()")
public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
logger.info("profileQuery() aspect Before");
Object pjp= thisJoinPoint.proceed();
logger.info("profileQuery() aspect After");
return pjp;
}
aspectj maven插件的POM片段
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>${java.version}</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<dependencies>
</dependencies>
<executions>
<execution>
<id>compile</id>
<phase>process-classes</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
maven编译器插件的POM代码段
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<source>${java.version}</source>
<target>${java.version}</target>
<useIncrementalCompilation>false</useIncrementalCompilation>
<excludes>
<exclude>**/*.*</exclude>
</excludes>
</configuration>
</plugin>
我试过使用Eclipse,也试过在Eclipse之外编译使用的命令mvn clean install -Dmaven.test.skip=true
在Tomcat 8.5.83上构建和部署没有问题,api也可以工作,但是方面没有像预期的那样被拦截。
您的POM和代码中有几个问题,我在此pull请求中修复了这些问题,例如:
-
您在
pluginManagement
部分配置了AspectJ Maven Plugin,但忘记在单独的plugins
部分实际将插件添加到项目中。 -
您的示例不包含测试基目录。因此,您需要删除目标
test-compile
,以避免构建错误。 -
当使用
org.codehaus.mojo:aspectj-maven-plugin
时,使用complianceLevel
是不够的,还需要指定source
和target
。或者您只是切换到更好的dev.aspectj:aspectj-maven-plugin
变体,那么complianceLevel
就足够了。 -
包名
aspect
不适合本地AspectJ,因为在AspectJ中它是保留关键字。所以我把你的包重命名为aop
。 -
你的切入点
call(* service.apiInnerService(..))
是错误的,你忘记了类名,应该用call(* service.MainService.apiInnerService(..))
代替。 -
本地AspectJ方面不应该有
@Component
注释,因为这是用于Spring AOP基于代理的方面的。你应该避免春季再次捡起它。
除了这些更改之外,我还从代码中删除了一些cruft,重新格式化了所有内容,并向AppConfig
添加了一个main方法,因此我可以轻松地从IDE运行应用程序并验证方面是否有效。但是在你的WAR中应该是一样的。
运行应用程序时,现在我看到:
Before Around :testAspectPointcut
Innerservice
After Around
Success
。,方面正在工作,拦截你的私有方法调用。但是请允许我说,如果您需要将方面应用于私有方法,那么您的应用程序很可能存在设计问题。
此版本有效:
@Aspect
public class ProfileCallAspect {
private static final Logger LOGGER = LogManager.getLogger(ProfileCallAspect.class);
@Pointcut("call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..))")
public void profileQuery() {
}
@Around("profileQuery()")
public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
LOGGER.info("ProfileCallAspect() Before");
Object res = thisJoinPoint.proceed();
LOGGER.info("ProfileCallAspect() After");
return res ;
}
}
在Spring项目中,你不能让它成为@Component,因为"call"但是@Configurable可以工作(通过@EnableSpringConfigured启用,并在依赖项中使用spring方面)。作为Aspect,它可以在没有日志的情况下工作,但如果你想做一些比日志更有用的事情,你可能需要在其中注入依赖项。当然,在proceed()和after()过程中的任何异常不会被记录,如果你想,你应该替换@Around条目:@Before @After, @AfterReturning, @ afterthrow根据你的需要。您还需要在pom.xml中使用aspectj-maven-plugin和spring-aspects作为aspectLibrary进行构建。(或等价于gradle)
我在pom.xml中删除后得到了这个工作。
不是
<pluginManagement>
<plugins>
<plugin>
</plugin>
</plugins>
</pluginManagement>
I changed to
<plugins>
<plugin>
</plugin>
</plugins>
实际上,最初的方法是我在pom.xml
中犯的一个错误如果在正确配置后还有其他编织问题,则得一分:在你使用的IDE之外编译项目,如果你从IDE构建项目,将会覆盖AJC (AspectJ编译器),编织可能不会发生