2016-08-12 35 views
0

說我有Spring AOP的配置一樣我該如何(或者應該)將Aspect Advice應用於動態代理?

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

和我有一些接口,ProxiableInterface。我

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

實現它我也有一個看點:

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

當我呼籲ProxiableInterface的方法,該方法看點不會被調用。有沒有一種方法來「登記」這個代理服務器,以便它被建議?我可以簡單地按照代理的InvocationHandler中的建議進行操作,但這會導致代碼重複,因爲此建議已經適用於代碼的其他區域。

+0

jic,也許你不需要這麼複雜的界面。而且由於你用new實例化,它不是代理,所以當然不會調用它。只是找到一些方法來得到它與豆,你應該沒問題 – Sarief

回答

2

我找到的解決方案是使用org.springframework.aop.aspectj.annotation.AspectJProxyFactory

在我的情況下,一個額外的複雜性是我想要代理的類是抽象的,而不是接口,這意味着Spring必須用CGLIB代替它而不是JDK代理。然而,這被證明是一種比煩人更有用的方式。

首先,我有一個抽象類:

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

(我已經重寫了一些對象的方法和讓他們final因爲他們原本被代理,但在這種情況下,我需要寫建議他們。)

然後,我有一個AspectJProxyFactory,並與原型範圍,因爲這樣一個bean:

@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

相關問題