描述:在使用AOP切面的时候Controller层可以正常切入进去,但是Service层内部方法调用切入不进去

大致情况

就算打注解放methodB上也不会进切面,Aop只支持外部调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.stereotype.Service;
/**
* 目标对象类
* @author Gufung
*/
@Service
public class TestAopService {

public void methodA() {
System.out.println("method A run");
//内部调用方法B时AOP的增强处理方法不会执行
methodB();
}

public void methodB() {
System.out.println("method B run");
}
}

解决方式

1.配置spring-context.xml

1
2
3
4
<!-- 通过@Aspect注解实现AOP -->
<!-- proxy-target-class="true"表示使用CGlib动态代理 -->
<!-- expose-proxy="true"暴露代理对象 -->
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

2.使用AopContext.currentProxy()获取代理对象方法,并且执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
/**
* 目标对象类
* @author Gufung
*
*/
@Service
public class TestAopService {

public void methodA() {
System.out.println("method A run");
//methodB();
//从spring上下文获取代理对象执行方法
((TestAopService) AopContext.currentProxy()).methodB();
}

public void methodB() {
System.out.println("method B run");
}
}

注意点

methodB一定要声明为public 否则进不去切面!!!

注解实现方法计时

1.自定义注解

1
2
3
4
5
6
7
8
9
/**
* 耗时统计
* @author Foam
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface TimeComsumingStatics {
String methodName();
}

2.aop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class TimeComsumingAOP {

private static final Logger log = LoggerFactory.getLogger(TimeComsumingAOP.class);

@Value("${timeCusming:false}")
public String openButton;

/**
* 基于注解定义切入点
* 对于注解了 @TimeComsumingStatics的方法进行拦截
* 表示标注了特定注解的目标方法链接点。如@annotation(com.dw.study.TestAnnotation)表示任何标注了@TestAnnotation注解的目标类方法。
**/
@Pointcut("@annotation(com.service.zl.vo.TimeComsumingStatics)")
public void aspect() {
}

/**
* 定时任务记录执行日志
* @return
*/
@Around(value = "aspect() && @annotation(timeComsumingStatics)")
public Object before(ProceedingJoinPoint proceedingJoinPoint,TimeComsumingStatics timeComsumingStatics) throws Throwable {
if("true".equals(openButton)){
long actStartTime = System.currentTimeMillis();
Object proceed = proceedingJoinPoint.proceed();
long actEndTime = System.currentTimeMillis();
String timecusming = (actEndTime - actStartTime) + "毫秒";
log.info(timeComsumingStatics.methodName() + "耗时:" + timecusming);
return proceed;
}else {
return proceedingJoinPoint.proceed();
}
}
}

3.application.properties

当timeCusming为true时开启接口耗时统计,false反之

1
timeCusming=true

4.注解使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
/**
* 目标对象类
* @author Gufung
*
*/
@Service
public class TestAopService {

public void methodA() {
System.out.println("method A run");
//methodB();
//从spring上下文获取代理对象执行方法
((TestAopService) AopContext.currentProxy()).methodB();
}

@TimeComsumingStatics(methodName = "调用methodB")
public void methodB() {
System.out.println("method B run");
}
}

5.结果

1
调用methodB耗时:17毫秒

参考文献