복붙노트

[SPRING] 다른 메소드 내부에서 메소드 호출을 위해 작동하지 않는 Spring AOP

SPRING

다른 메소드 내부에서 메소드 호출을 위해 작동하지 않는 Spring AOP

ABC.java에는 두 가지 메소드가 정의되어 있습니다.

public void method1(){
   .........
   method2();
  ...........
}


public void method2(){
  ...............
  ...............  
}

나는 방법 2의 호출에 AOP를 가지고 싶다. 그래서, 하나의 클래스, AOPLogger.java를 만들었고, aspect 기능을 checkAccess 메소드에서 제공했다. 설정 파일에서, 나는 아래와 같이했다.

<bean id="advice" class="p.AOPLogger" />
<aop:config>
  <aop:pointcut id="abc" expression="execution(*p.ABC.method2(..))" />
  <aop:aspect id="service" ref="advice">
    <aop:before pointcut-ref="abc" method="checkAccess" />          
  </aop:aspect>
</aop:config>

하지만 내 method2가 호출되면 AOP 기능이 호출되지 않습니다. 즉 AOPLogger 클래스에서 checkAccess 메소드가 호출되지 않습니다.

나는 실종 됐어?

해결법

  1. ==============================

    1.애스펙트는 빈을 둘러싼 프록시에 적용됩니다. 빈에 대한 참조를 얻을 때마다 config에서 실제로 참조되는 클래스가 아니라 관련 인터페이스를 구현하고 실제 클래스에 위임하고 AOP와 같은 기능을 추가하는 가상 클래스입니다.

    애스펙트는 빈을 둘러싼 프록시에 적용됩니다. 빈에 대한 참조를 얻을 때마다 config에서 실제로 참조되는 클래스가 아니라 관련 인터페이스를 구현하고 실제 클래스에 위임하고 AOP와 같은 기능을 추가하는 가상 클래스입니다.

    위의 예제에서 클래스를 직접 호출하는 반면, 클래스 인스턴스가 Spring bean으로 다른 인스턴스에 주입되면 프록시로 주입되므로 메소드 호출이 프록시에서 호출됩니다 (그리고 aspect가 트리거됩니다). )

    위의 내용을 달성하려면 method1 / method2를 별도의 빈으로 나눌 수도 있고 스프링 지향적 인 AOP 프레임 워크를 사용할 수도 있습니다.

    스프링 박사는 이것을 상세히 설명하고 몇 가지 해결 방법 (위의 첫 번째 제안 포함)

  2. ==============================

    2.그것은 자기 주입 사용하여 수행 할 수 있습니다. 삽입 된 인스턴스를 통해 내부 메서드를 호출 할 수 있습니다.

    그것은 자기 주입 사용하여 수행 할 수 있습니다. 삽입 된 인스턴스를 통해 내부 메서드를 호출 할 수 있습니다.

    @Component
    public class Foo {
        @Resource
        private Foo foo;
    
        public void method1(){
            ..
            foo.method2();
            ..
        }
        public void method2(){
            ..
        }
    }
    

    Spring 4.3부터 @Autowired를 사용하여 수행 할 수도 있습니다.

  3. ==============================

    3.나는 같은 종류의 문제를 겪었고 Spring의 ApplicationContextAware, BeanNameAware를 구현하고 아래와 같이 해당 메소드를 구현함으로써 극복했다.

    나는 같은 종류의 문제를 겪었고 Spring의 ApplicationContextAware, BeanNameAware를 구현하고 아래와 같이 해당 메소드를 구현함으로써 극복했다.

    class ABC implements ApplicationContextAware,BeanNameAware{
    
          @Override
          public void setApplicationContext(ApplicationContext ac) throws BeansException {
              applicationContext=ac;
          }
    
          @Override
          public void setBeanName(String beanName) {
              this.beanName=beanName;
          }
          private ApplicationContext applicationContext;
          private String beanName;
    }
    

    나는 이것을 교체했다. with ((ABC) applicationContext.getBean (beanName)). 같은 클래스의 메서드를 호출하는 동안. 이렇게하면 동일한 클래스의 메서드에 대한 호출이 프록시를 통해서만 수행됩니다.

    그래서 method1 ()은로 바뀝니다.

     public void method1(){
        .........
        ((ABC) applicationContext.getBean(beanName)).method2();
        ...........
      }
    

    희망이 도움이됩니다.

  4. ==============================

    4.Spring AOP 프레임 워크는 "프록시"기반이며 매우 잘 설명되어있다.     http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

    Spring AOP 프레임 워크는 "프록시"기반이며 매우 잘 설명되어있다.     http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

    Spring이 애스펙트 (예 : "ABC")와 같이 구성된 빈을 생성 할 때, 실제 빈처럼 작동하는 "프록시"객체를 실제로 생성한다. 프록시는 단순히 "실제"객체에 호출을 위임하지만이 간접 참조를 작성함으로써 프록시는 "advice"를 구현할 기회를 얻습니다. 예를 들어 조언을 통해 각 메소드 호출에 대한 메시지를 기록 할 수 있습니다. 이 스키마에서 실제 객체 ( "method1")의 메소드가 동일한 객체 (예 : method2)의 다른 메소드를 호출하면 그림의 프록시없이 이러한 호출이 발생하므로 어떤 조언을 구현할 기회가 없습니다.

    귀하의 예제에서, method1 ()이 호출 될 때, 프록시는 이제까지해야 할 일을 할 수있는 기회를 얻게됩니다. 그러나 method1 ()이 method2 ()를 호출하면 그림에 어떤 면도 없습니다. 어쨌든 method2가 다른 bean으로부터 호출되면, 프록시는 advice를 수행 할 수있을 것이다.

    희망이 도움이됩니다.

    감사, 라구

  5. ==============================

    5.@Autowired를 사용하면 작동합니다. 내부 메소드를 this.method ()로 호출하는 대신 다음과 같이 할 수 있습니다.

    @Autowired를 사용하면 작동합니다. 내부 메소드를 this.method ()로 호출하는 대신 다음과 같이 할 수 있습니다.

    @Autowired
    Foo foo;
    

    전화 :

    foo.method2();
    
  6. ==============================

    6.당신이 성취하고자하는 것은 불가능합니다. 설명은 Spring Reference Documentation을 참조하십시오.

    당신이 성취하고자하는 것은 불가능합니다. 설명은 Spring Reference Documentation을 참조하십시오.

  7. ==============================

    7.Spring 문서, 5.6.1 장 AOP 프록시 이해에 나와 있듯이, 당신이 할 수있는 또 다른 방법이있다 :

    Spring 문서, 5.6.1 장 AOP 프록시 이해에 나와 있듯이, 당신이 할 수있는 또 다른 방법이있다 :

    public class SimplePojo implements Pojo {
    
        public void foo() {
            // this works, but... gah!
            ((Pojo) AopContext.currentProxy()).bar();
        }
    
        public void bar() {
            // some logic...
        }
    }
    

    저자는이 방법을 권장하지 않지만. 때문에:

  8. ==============================

    8.이 방법을 사용하면 Spring 애플리케이션 외부에서이 클래스를 사용할 수있다.

    이 방법을 사용하면 Spring 애플리케이션 외부에서이 클래스를 사용할 수있다.

    @Component
    public class ABC {
    
        @Resource
        private ABC self = this;
    
        public void method1() {
            self.method2();
        }
    
        public void method2() {
    
        }
    
    }
    
  9. ==============================

    9.@EnableAspectJAutoProxy (exposeProxy = true)를 사용하여 호출에 주석을 달고 ((Class) AopContext.currentProxy ()).

    @EnableAspectJAutoProxy (exposeProxy = true)를 사용하여 호출에 주석을 달고 ((Class) AopContext.currentProxy ()).

    커플 링이 증가하므로 엄격하게 권장하지 않습니다.

  10. from https://stackoverflow.com/questions/13564627/spring-aop-not-working-for-method-call-inside-another-method by cc-by-sa and MIT license