2016-08-12 2 views
0

내가 스프링 AOP가어떻게 동적 프록시에 Aspect Advice를 적용 할 수 있습니까?

@Configuration 
@EnableAspectJAutoProxy 
@ComponentScan 
class Config { ... } 

처럼 구성하고 내가 ProxiableInterface을 몇 가지 인터페이스를 가지고 있다고 가정 해.

@Aspect 
class SomeAspect { 
    @Around("execution(package.ProxiableInterface.*)") 
    Object doStuffAround(ProceedingJoinPoint pjp) { ... } 
} 

내가 ProxiableInterface에 메소드를 호출

는, 가로 세로 메서드가 호출되지 않습니다 : 나는 또한 화면이

ProxiableInterface pi = (ProxiableInterface) Proxy.newProxyInstance(
    applicationContext.getClassLoader(), 
    new Class[] {ProxiableInterface.class}, 
    (proxy, method, args) -> { ... }); 

으로 구현합니다. 이 프록시를 "등록"하여 정렬되도록하는 방법이 있습니까? 프록시의 InvocationHandler 내에서 조언을 수행하는 것만으로 간단하게 할 수 있지만이 권고가 이미 코드의 다른 영역에도 적용되어 있으므로 코드가 중복 될 수 있습니다.

+0

jic, 아마도 그러한 복잡한 인터페이스는 필요하지 않습니다. 그리고 당신이 새로운 것으로 인스턴스화하기 때문에 그것은 프록시가 아니므로 호출되지 않습니다. 그냥 콩으로 얻으려면 어떤 방법을 찾으십시오 그리고 당신은 ok이어야합니다 – Sarief

답변

2

내가 발견 한 해결책은 org.springframework.aop.aspectj.annotation.AspectJProxyFactory입니다.

필자의 경우 필자가 추가하고자하는 클래스는 프록시가 아닌 추상 클래스이고, 인터페이스는 아니며, Spring은 JDK 프록시가 아닌 CGLIB로 프록시해야한다는 것을 의미한다. 그러나 이것은 성가신 것보다 더 유용하다는 것을 증명했습니다. 먼저

, 나는 추상 클래스가 있습니다

public abstract class Something { 

    abstract void doWhatever(); 

    @Override 
    public final boolean equals(Object o) { 
     return this == o; 
    } 

    @Override 
    public final int hashCode() { 
     return System.identityHashCode(this); 
    } 

    @Override 
    public final String toString() { 
     return getClass().getName() + " " + hashCode(); 
    } 
} 

(I 일부 개체 방법을 무시하고 달리 프록시 될 수 있기 때문에 그들을 final을했습니다,하지만 그 경우에 나는 그들에게 조언을 작성해야 .) 그런 다음

내가 가진 AspectJProxyFactory과 같은 프로토 타입 범위를 가진 빈 :

@Configuration 
@EnableAspectJAutoProxy 
class Config { 

    private static final AspectJProxyFactory proxyFactory = new AspectJProxyFactory(); 
    static { 
     proxyFactory.setTargetClass(Something.class); 
     proxyFactory.addAspect(SomeAspect.class); 
    } 

    @Bean 
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
    Something something() { 

     return proxyFactory.getProxy(); 
    } 
} 

주 그 Something Spring AOP가이를 인식하도록 Bean이어야합니다. 그리고 이것은 화면은 다음과 같습니다

@Aspect 
public class SomeAspect { 

    @Around("execution(void org.luc.Something.doWhatever())") 
    void around(ProceedingJoinPoint pjp) throws Throwable { 

     System.out.println(pjp.getThis().toString() + ": I've been advised"); 
    } 
} 

이 방법 나는 AOP 자동 프록시에 의해 권고 된 것입니다 프록시 공장, 구별 인스턴스를 얻을 수 있습니다.

Something something1 = applicationContext.getBean(Something.class); 
    Something something2 = applicationContext.getBean(Something.class); 

    Assert.assertEquals(something1, something1); 
    Assert.assertNotEquals(something1, something2); 

    something1.doWhatever(); 
    something2.doWhatever(); 

같은 것을 인쇄 :

org.luc.Something $$ EnhancerBySpringCGLIB $$ cadae9a8 638486177 : 나는 을 사전에 알고 있던 한 org.luc.Something $$ EnhancerBySpringCGLIB $$ cadae9a8 426019904 : 나는 권고를 받았습니다.

+0

이것은 다소 깔끔합니다. Spring AOP가 아니라 AspectJ를 사용하므로이 프록시 문제는 결코 발생하지 않는다. 하지만 Spring AOP 사용자에게는 멋진 기능입니다. :-) – kriegaex

관련 문제