@Before、@After注解的方法都不执行

来源:2-5 参数匹配

笑傲江湖3955759

2018-07-06 11:40

@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方法都没有执行

写回答 关注

3回答

  • 老丶斑鸠
    2019-10-21 17:43:55

    他织入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代理的话,就不是继承目标对象了,是实现目标对象的接口,然后把接口的实现注入到代理类的属性中,走回调的话就是调用这个属性的方法。

  • 老丶斑鸠
    2019-10-21 17:35:46

    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>


  • 慕先生8495945
    2018-07-06 18:52:32

    你将private void printInteger(Integer i)方法写到service层,类上加上注解@Service,然后再从Controller层用@Autowried注入调用就行了.

    匹配表达式改成within(com.imooc.miaosha.service.*)

探秘Spring AOP

让我们一起探秘Spring Aop

61205 学习 · 59 问题

查看课程

相似问题