복붙노트

[SPRING] Spring AOP가 런타임에 외부 항아리를 짜지 않는 이유는 무엇입니까?

SPRING

Spring AOP가 런타임에 외부 항아리를 짜지 않는 이유는 무엇입니까?

나는 Spring 3에서 빌드 된 자바 애플리케이션을 가지고있다.이 프로젝트는 의존성 (dependency)으로서 다른 항아리를 가지고있다.

이 종속성에는 @ org.aspectj.lang.annotation.Aspect 클래스가 포함됩니다 (com.aspectprovider.aspects.MyAspect라고 말하면 됨). Foo 인터페이스를 구현 한 클래스에서 메소드를 짜기위한 @Before advice가있다. 같은 것 :

@Before("execution(* com.project.Foo.save(..))")

Foo 인터페이스는 "프로젝트"내부 또는 다른 병에있을 수 있습니다. 이 예제에서는 중요하지 않습니다.

내 프로젝트에는 Foo를 구현하는 클래스가 포함되어 있습니다. 그것들은 내가 물론 길쌈하려는 수업들입니다.

My Spring 애플리케이션 컨텍스트 설정 파일 (applicationContext.xml)에는 다음 행이있다.

<aop:aspectj-autoproxy />

aspect를 bean으로 선언하고 몇 가지 속성을 주입한다.

<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect"
  factory-method="aspectOf" >
  <property name="someproperty" value="somevalue" />
</bean>

Trough 로깅 MyAspect가 인스턴스화되고 속성이 주입되는 것을 볼 수 있습니다. 그러나 save 메소드는 인터셉트되지 않습니다. 이게 문제 야.

항아리에서 애스펙트 클래스를 Spring이있는 애플리케이션으로 복사하면 작동합니다. 이러한 측면이 외부 항아리에 포함되어있을 때 save 메서드는 가로 챌 수 없습니다. 모든 단서?

편집 : 어떻게 푸의 저장 메서드를 호출 오전 :

//in a JSF managed bean
@Inject
private Foo myFoo;  //there's a implementation of Foo in a package that spring is looking at. So it is injected correctly.

public String someAction() {
    myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar
}


//in a class with a main method
void main(String[] ars) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    //right after the previous line, I can see in the log that MyAspect is instantiated.
    Foo myFoo = ac.getBean(Foo.class);
    myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar
}

기본적으로 내 applicationContext.xml에는 다음과 같은 행이 있습니다.

<context:annotation-config />
<context:component-scan base-package="com.project" />
<context:component-scan base-package="com.aspectprovider.aspects" />
<aop:aspectj-autoproxy />
<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect" factory-method="aspectOf" >
    <property name="someproperty" value="somevalue" />
</bean>

나는 아무것도 넣어 줄 필요가 없다고 생각한다.

<context:component-scan  base-package="com.project">
    <context:include-filter type="aspectj" expression="com.aspectprovider.aspects.*" />
</context:component-scan>

해결법

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

    1.나도 같은 문제가있어. 나는이 문제를 maven으로 해결했다. aspectj-maven-plugin과 weaveDependency 옵션을 확인하십시오.

    나도 같은 문제가있어. 나는이 문제를 maven으로 해결했다. aspectj-maven-plugin과 weaveDependency 옵션을 확인하십시오.

    http://mojo.codehaus.org/aspectj-maven-plugin/weaveJars.html

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

    2.클래스가 애플리케이션과 패키지화되어있을 때 완벽하게 작동한다고 생각하면 클래스로드 문제 만 생각할 수 있습니다.

    클래스가 애플리케이션과 패키지화되어있을 때 완벽하게 작동한다고 생각하면 클래스로드 문제 만 생각할 수 있습니다.

    그것은 귀하의 응용 프로그램에 다음 AOP가 모든 클래스를 스캔해야 할 때 그때 그것은 모든 오른쪽 항아리와 오른쪽 클래스 로더를 참조하는 것입니다 검사를 번들로 잘 작동합니다. 하지만 이제이를 제거하고 JAR 파일로 설정하면 다른 모든 제 3 자 항아리가있는 클래스 로더에서 스캔됩니다.

    100 % 확신 할 수는 없지만 다음과 같이 될 수 있습니다.

    Bootstrap Classloader <- Third Party Classloader  <- Application Class Loader (with all your classes)
                                  \                         \
                                   aspectj.jar               spring.jar
    

    aspect.jar가 해당 클래스 로더 아래에서 스캔 중이면 '모든 클래스'를 볼 수 없습니다. 이것을 확인하는 한 가지 방법은 앱의 힙 덤프를 얻는 것입니다. Eclipse MAT에 대해 실행하고 클래스 로더 탐색기를 확인한 다음 애스펙트 클래스를 찾으십시오. 응용 프로그램과 동일한 클래스 로더 아래에 있지 않으면 tomcat이 제 3 자 라이브러리에 응용 프로그램 클래스를 알리는 방법을 찾아야합니다.

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

    3.Spring AOP 프록시 대신 aspectJ LTW를 시도 할 수도있다. 이렇게하려면 META-INF에 aop.xml을 추가하십시오.

    Spring AOP 프록시 대신 aspectJ LTW를 시도 할 수도있다. 이렇게하려면 META-INF에 aop.xml을 추가하십시오.

    <!DOCTYPE aspectj PUBLIC
            "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
    <aspectj>
        <weaver>
            <!-- only weave classes in this package -->
            <include within="org.springbyexample.aspectjLoadTimeWeaving.*" />
        </weaver>
        <aspects>
            <!-- use only this aspect for weaving -->
            <aspect name="org.springbyexample.aspectjLoadTimeWeaving.PerformanceAdvice" />
        </aspects>
    </aspectj>
    

    그리고 이것은 config의 스프링 부분입니다.

    자세한 내용은 여기를 참조하십시오 : http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-aj-ltw

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

    4.액션 북의 AspectJ : 프록시 기반 AOP와 함께 사용되는 aspect (@AspectJ를 사용하여 선언 됨) 또는 XML 기반 구문)은 Spring Bean이므로 aspectOf () 접근 방식을 사용하지 않아야합니다 인스턴스화합니다.

    액션 북의 AspectJ : 프록시 기반 AOP와 함께 사용되는 aspect (@AspectJ를 사용하여 선언 됨) 또는 XML 기반 구문)은 Spring Bean이므로 aspectOf () 접근 방식을 사용하지 않아야합니다 인스턴스화합니다.

    그것을 정상적으로 선언하고 그것이 효과가 있는지보십시오 :

    <bean id="myAspect" class="com.project.MyAspect">
      <property name="someproperty" value="somevalue" />
    </bean>
    
  5. ==============================

    5.Spring의 applicationContext xml config에서 애스펙트를 선언하고 애노테이션을 제거하는 결과를 얻었습니다.

    Spring의 applicationContext xml config에서 애스펙트를 선언하고 애노테이션을 제거하는 결과를 얻었습니다.

    지금까지는 maven 용 aspectj 플러그인을 사용하고 있었지만, Eclipse에서 클래스를 변경할 때마다 $ mvn 컴파일을 실행해야했습니다 (Eclipse가 측면을 알지 못하고 클래스가없는 클래스를 컴파일했기 때문에). MyAspect를 사용할 다른 사람에게 말하는 끔찍한 일.

    그런 다음 설정 파일을 만들고 문서화했습니다. MyAspect를 사용하려면이 구성 규칙을 스프링 컨텍스트 구성으로 가져옵니다.

  6. ==============================

    6.ApectWerks를 살펴보면 로딩 타임 짜기가됩니다. http://aspectwerkz.codehaus.org/weaving.html

    ApectWerks를 살펴보면 로딩 타임 짜기가됩니다. http://aspectwerkz.codehaus.org/weaving.html

  7. from https://stackoverflow.com/questions/5956490/why-spring-aop-is-not-weaving-external-jars-at-runtime by cc-by-sa and MIT license