@Aspect @Component public class AspectConfig { @Pointcut("args(Integer) && within(com.imooc.miaosha.controller.*)") public void matchArgs() {} @Before("matchArgs()") public void before_1() { System.out.println("####before1"); } @After("matchArgs()") public void after_1() { System.out.println("####after1"); } }
package com.imooc.miaosha.controller; @Controller @RequestMapping("/demo") public class SampleController { @RequestMapping("/hello") @ResponseBody public Result<String> home() { System.out.println("hello"); printInteger(100); return Result.success("Hello,world"); } private void printInteger(Integer i) { System.out.println("this is "+i); } }
运行结果:访问http://localhost:8080/demo/hello,正常运行,没有报异常,但是AspectConfig类中的before_1、after_1方法都没有执行
他织入AOP增强代码的时候相当于就是这样的一个结构
public class Proxy extend SampleController{
@Overwired
public
Result<String> home() {
System.out.println(
"hello"
);
super.printInteger(
100
);
return
Result.success(
"Helloworld"
);
}
@Overwired
private
void
printInteger(Integer i) {
before_1();
super.
printInteger(i);
after_1();
}
public
void
before_1() {
System.out.println(
"####before1"
);
}
public
void
after_1() {
System.out.println(
"####after1"
);
}
}
大体上这个意思,这个是CGLIB代理,within是使用CGLIB代理的, 如果时JDK代理的话,就不是继承目标对象了,是实现目标对象的接口,然后把接口的实现注入到代理类的属性中,走回调的话就是调用这个属性的方法。
sampleController本身调用home()方法时是CGLIB代理对象,但是执行home()方法时你切面advice没有做增强处理,然后proxy代理类再回调目标对象类的printInteger(Integer i)方法,这个时候也就是IOC容器中的sampleController 的 bean本身。所以自然不会触发advice方法。
几个解决办法。
1.从applicationContext(beanFactory)中重新获取sampleController类的bean,spring在注入的时候会检查bean是否由代理类,如果有的话就会赋值为代理类,这个时候你就重新得到了代理对象了,然后在方法内部用代理对象重新printInteger(Integer i)方法。
2.开启代理暴露。
注解形式:@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true);
xml形式:
<aop:config expose-proxy="true"></aop:config>
你将private
void
printInteger(Integer i)方法写到service层,类上加上注解@Service,然后再从Controller层用@Autowried注入调用就行了.
匹配表达式改成within(com.imooc.miaosha.service.*)