我已经通过perf4J网站的以下链接,并做了同样的事情:http://perf4j.codehaus.org/devguide.html#Using_Spring_AOP_to_Integrate_Timing_Aspects
在我的spring.xml中添加了以下内容.
<aop:aspectj-autoproxy/>
<bean id="timingAspect" class="org.perf4j.log4j.aop.TimingAspect"/>
<bean id="wscClientBase" class="com.xyz.csa.core.common.WscClientBase"/>
Run Code Online (Sandbox Code Playgroud)
在类WscClientBase中,我使用@Profiled注释的以下方法.
@Profiled(tag = "SOAPCALLTEST")
public Object sendMessage(Object message) {
String msg = message.toString();
if (msg.indexOf(' ') > 1) {
msg = msg.substring(1, msg.indexOf(' '));
}
try {
Object ret = marshalSendAndReceive(message);
return ret;
} catch (RuntimeException ex) {
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
我没有在应用程序日志中看到perf4j TimingLogger语句.但是,如果我使用它(如下没有注释),我会成功地看到日志语句.
public Object sendMessage(Object message) {
String msg = message.toString();
if (msg.indexOf(' ') > 1) {
msg = msg.substring(1, msg.indexOf(' '));
}
StopWatch stopWatch …Run Code Online (Sandbox Code Playgroud) 我有一个spring应用程序 ,我按如下方式编写测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class MyTest {
}
Run Code Online (Sandbox Code Playgroud)
当我尝试创建另一个测试类并尝试运行该应用程序时,我在新的测试类上得到以下异常:
ERROR [main] (TestContextManager.java:324) - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecut
r@22e85825] to prepare test instance [Testing.MyTest2@43f2f70a]
org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)
at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:386)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:111)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at …Run Code Online (Sandbox Code Playgroud) 我正在尝试测试@AsyncSpring的注释是否在我的项目中按预期工作.但事实并非如此.
我有这个测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = GlobalConfiguration.class)
public class ActivityMessageListenerTest {
@Autowired
private ActivityMessageListener activityMessageListener;
private Long USER_ID = 1l;
private Long COMPANY_ID = 2l;
private Date DATE = new Date(10000000);
private String CLASSNAME = "className";
private Long CLASSPK = 14l;
private Integer TYPE = 22;
private String EXTRA_DATA = "extra";
private Long RECIVED_USER_ID = 99l;
@Before
public void setup() throws Exception {
}
@Test
public void testDoReceiveWithException() throws Exception {
System.out.println("Current thread " + Thread.currentThread().getName());
Map<String, Object> values …Run Code Online (Sandbox Code Playgroud) 在我们的应用程序中,我们有几个(实际上很多,大约30个)Web服务.每个Web服务都驻留在自己的WAR文件中,并且具有自己的Spring上下文,该上下文在应用程序启动时初始化.
我们还有许多应用于Web服务类的注释驱动的方面类.在开始时,poincut表达式看起来像这样:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..))")
public void methodsToBeLogged() {
}
Run Code Online (Sandbox Code Playgroud)
并且通过配置输入启用了AOP服务.
但是当网络服务的数量增加时,我们开始OutOfMemoryException在服务器上体验s.在进行一些分析和分析之后,看起来内存是由AspectJExpressionPointcut类的实例保存的缓存占用的.
每个实例的缓存大约是5 MB.由于我们有3个方面和30个服务,因此共有90个实例共存储了450MB的数据.
在检查了缓存的内容后,我们意识到它包含了WAR中存在的所有类的Java反射方法实例,即使是那些不属于my.package.service.business包的类.修改了切点表达式后还有附加within条款:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..)) &&
within(my.package.service.business..*)")
public void methodsToBeLogged() {
}
Run Code Online (Sandbox Code Playgroud)
内存使用量再次降至正常水平.并且所有AspectJExpressionPointcut实例总共花费不到1MB.
有人可以解释为什么会这样吗?为什么第一点切割表达还不够?为什么AspectJExpressionPointcut不共享缓存?
我在这里检查了测试项目:https://github.com/loesak/spring-aop-injection-bug
给出以下pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.loesoft</groupId>
<artifactId>spring-aop-injection-bug</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<spring.framework.bom.version>4.2.0.RELEASE</spring.framework.bom.version>
<spring.retry.version>1.1.2.RELEASE</spring.retry.version>
<aspectj.aspectjweaver>1.8.7</aspectj.aspectjweaver>
<java.version>1.7</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.framework.bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${spring.retry.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.aspectjweaver}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
和Spring配置:
package com.loesoft.spring.aop.injection.bug;
import org.springframework.beans.factory.annotation.Autowired;
import …Run Code Online (Sandbox Code Playgroud) 我有这个服务/控制器方法:
public ResponseEntity<PolicyDTO> addPolicy(@Valid @RequestBody PolicyDTO policy)
throws InternalServerException, BadRequestException {
log.debug("Adding a new policy");
}
Run Code Online (Sandbox Code Playgroud)
注意方法参数中的@Valid批注
对于此控制器,我们定义了以下方面类:
@Aspect
@Component
public class BackwardsCompatibilityHandler {
@Around("execution(* com.company.PolicyController.addPolicy(..))")
public Object ControllerMethod(JoinPoint jp)
{
// DO Code before and after the method call
}
Run Code Online (Sandbox Code Playgroud)
这方面/代理背后的主要原因是拦截方法调用,并对输入参数/返回的结果进行一些前/后处理。
我们现在面临的主要问题是@Valid批注在实际执行代码之前和之后的方面之前进行处理。
关于如何使验证检查在AOP代码中运行的任何想法?我知道有一种方法可以通过手动调用方法内部的验证器来做到这一点,但是我不想过多地触摸现有代码...因此,除此以外,还有其他任何想法...
现在执行的顺序是:
我们希望有更多类似的东西(首先是我们的代码,然后是Valid注释):
请跳过编译器错误等,该代码仅用于演示目的,不是真正的代码:)
我创建了一个名为BaseCron的bean,它有一个executeBefore()在spring的下面配置中配置的方法,用于拦截Crons类的所有方法调用并在它们之前执行.
该executeBefore()方法有一些验证.我之前验证了某些条件,如果它们是假的,我就是抛出异常.抛出异常会导致方法失败,因此Crons类中的方法不会执行.
它工作正常.
你可以建议一些其他的方法,我可以停止执行Crons类而不抛出异常.我试过回来但是没用.
<bean id="baseCronBean" class="com.myapp.cron.Jkl">
</bean>
<aop:config>
<aop:aspect id="cron" ref="baseCronBean">
<aop:pointcut id="runBefore" expression="execution(* com.myapp.cron.Abc.*.*(..)) " />
<aop:before pointcut-ref="runBefore" method="executeBefore" />
</aop:aspect>
</aop:config>
Run Code Online (Sandbox Code Playgroud)
Abc课程:
public class Abc {
public void checkCronExecution() {
log.info("Test Executed");
log.info("Test Executed");
}
}
Run Code Online (Sandbox Code Playgroud)
Jkl课程:
public class Jkl {
public void executeBefore() {
//certain validations
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个自定义记录器@Aspect,我希望它始终在最后运行,这样无论控制器返回什么响应,它都会被记录到数据库中(所以我@Order(1)在这方面添加了一个)。我还编写了一个错误处理程序,用于@ControllerAdvice处理所有意外异常并返回500自定义响应正文,并且我希望记录器也记录它,因此我@Order(2)在其上添加了一个,但是看起来放置@Order注释并没有安排Spring Aspect 和 Spring ControllerAdvice 之间的命令,那么如何让我的错误处理程序始终在记录器之前运行?(当然,无需将我的错误处理程序转换为另一个 Spring Aspect)
据我了解,SpringAutowiredAnnotationBeanPostProcessor在postProcessBeforeInitialization舞台上管理自动装配机制。但它如何注入应该在postProcessAfterInitialization舞台上创建的代理呢?
假设我有这个 Spring 配置
@Service
class RegularBean {
// injected on postProcessBeforeInitialization stage
@Autowired
private TransactionBean tBean;
// invoked in between of postProcessBeforeInitialization and postProcessAfterInitialization
@PostConstruct
void init() {
tBean.transactionMethod();
}
}
@Service
class TransactionBean {
// transactional proxy is created on postProcessAfterInitialization stage
@Transactional
public void transactionMethod() { ... }
}
Run Code Online (Sandbox Code Playgroud)
事务代理是在postProcessAfterInitialization舞台上创建的。但@PostConstruct在它之前被调用。注入是否tBean包含事务代理?如果是这样,那为什么呢?因为不应该这样。如果不包装,那么以后的交易将如何处理?
假设我用构造函数注入替换字段注入。它会以某种方式改变行为吗?
据我了解,Spring AOP一般涉及:
为什么不一直使用 CGLIB 代理呢?我期望获得以下收益:
spring-aop ×10
spring ×9
aop ×3
java ×2
aspectj ×1
cglib ×1
expression ×1
junit ×1
log4j ×1
perf4j ×1
pointcut ×1
seam ×1
spring-boot ×1
spring-mvc ×1
validation ×1