Spring AOP nie działa dla wywołania metody wewnątrz innej metody

Istnieją dwie metody zdefiniowane w ABC.java

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


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

I want to have AOP on call of method2 .So, Stworzyłem jedną klasę, AOPLogger.java,o funkcjonalności aspect dostarczonej w metodzie checkAccess
W pliku konfiguracyjnym zrobiłem coś takiego jak poniżej

<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>

Ale kiedy moja method2 jest wywoływana, funkcja AOP nie jest wywoływana, tzn. checkAccess metoda nie jest wywoływana z klasy AOPLogger.

Any thing I am zaginęła?

Author: Anand, 2012-11-26

7 answers

Aspekt jest stosowany do proxy otaczającej fasolę. Zauważ, że za każdym razem, gdy pojawi się odniesienie do bean, nie jest to w rzeczywistości Klasa, do której odwołujesz się w konfiguracji, ale syntetyczna Klasa implementująca odpowiednie interfejsy, delegująca do rzeczywistej klasy i dodająca funkcjonalności, takie jak AOP.

W powyższym przykładzie wywołujesz bezpośrednio na klasie, podczas gdy jeśli ta instancja klasy zostanie wstrzyknięta do innej jako Spring bean, zostanie ona wstrzyknięta jako jej proxy, w związku z tym wywołania metod będą wywoływane na serwerze proxy (a Aspekty zostaną wywołane)

Jeśli chcesz osiągnąć powyższe, możesz podzielić method1/method2 do osobnych fasolek, lub użyć ramy AOP nie zorientowanej na wiosnę.

The Spring doc to szczegóły i kilka obejść (w tym moja pierwsza sugestia powyżej)

 43
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 05:40:58

Można to zrobić za pomocą samodzielnego wstrzykiwania. Można wywołać wewnętrzną metodę poprzez instancję iniekcyjną:

@Component
public class Foo {
    @Resource
    private Foo foo;

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

Od wiosny 4.3 można to również zrobić za pomocą @Autowired.

Od 4.3, @Autowired rozważa również autopromocję do wtrysku, tj. odniesienia do fasoli, która jest obecnie wstrzykiwana.

 27
Author: Konstantin Zyubin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-30 14:48:27

Miałem ten sam problem i pokonałem go wdrażając Spring ' S ApplicationContextAware,BeanNameAware i wdrożenie odpowiednich metod, jak poniżej.

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;
}

Następnie zamieniłem this. na ((ABC) applicationContext.getBean(beanName)). podczas wywoływania metod tej samej klasy. Zapewnia to, że wywołania metod tej samej klasy odbywają się tylko przez serwer proxy.

Więc method1() zmienia się na

 public void method1(){
    .........
    ((ABC) applicationContext.getBean(beanName)).method2();
    ...........
  }
Mam nadzieję, że to pomoże.
 5
Author: pavan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-16 03:53:28

Spring AOP framework jest oparty na "proxy" i jest bardzo dobrze wyjaśniony tutaj: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

Kiedy Spring konstruuje fasolę, która jest skonfigurowana z aspektem( jak " ABC " w twoim przykładzie), tworzy obiekt "proxy", który działa jak prawdziwa fasola. Proxy po prostu deleguje wywołania do" prawdziwego " obiektu, ale tworząc tę indirection, proxy otrzymuje możliwość wdrożenia "porady". Na przykład Twoja porada może zapisać wiadomość dla każdego połączenia metodycznego. W tym schemacie, jeśli metoda w rzeczywistym obiekcie ("method1") wywoła inne metody w tym samym obiekcie (np. method2), wywołania te występują bez proxy na obrazku, więc nie ma szans na zaimplementowanie żadnej porady.

W twoim przykładzie, gdy wywołana zostanie metoda method1 (), proxy będzie miał szansę zrobić to, co powinien, ale jeśli metoda method1 () wywoła metodę method2 (), nie ma żadnego aspektu w zdjęcie. Jak zawsze, jeśli method2 zostanie wywołany z innej Beany, proxy będzie w stanie przeprowadzić poradę.

Mam nadzieję, że to pomoże.

Dzięki, Raghu

 2
Author: Raghuram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 19:54:12

Używanie @Autowired działa. Zamiast wywoływać wewnętrzną metodę jako this.method(), możesz wykonać:

@Autowired
Foo foo;

A następnie wywołanie:

foo.method2();
 2
Author: Rashmingadhvi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 06:45:57

Nie jest możliwe, co chcesz osiągnąć. Wyjaśnienie znajduje się w dokumentacji źródłowej .

 0
Author: Uwe Plonus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 12:17:45

Jak wskazano w Spring docs , Rozdział 5.6.1 zrozumienie proxy AOP, jest inny sposób, który możesz zrobić:

public class SimplePojo implements Pojo {

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

    public void bar() {
        // some logic...
    }
}

Chociaż autor tego nie poleca. Ponieważ:

To całkowicie łączy Twój kod Z Spring AOP, i sprawia, że sama klasa jest świadoma faktu, że jest używana w kontekście AOP, który leci w obliczu AOP. Wymaga to również dodatkowej konfiguracji podczas tworzenia proxy.

 0
Author: Qianyue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-10 07:05:50