AOP代理對象生成

 

 AOP(Aspect-OrientedProgramming,面向方面編程)是OOP(Object-Oriented Programing,面向對象編程)的良好補充與完善,後者側重於解決html

從上到下的存在明顯層次邏輯關係的問題,而前者則側重於由左至右的水平散佈的無明顯邏輯關係但具有相同行爲的問題。AOP抽象的是相同的行爲而非正則表達式

關聯的行爲,用於提供通用服務支持,而非業務邏輯處理,其核心思想是「將應用程序中的商業邏輯同對其提供支持的通用服務進行分離。spring

AOP植入有多種不一樣方式,主要分爲如下三種方式:編程

  1. 編譯期植入
  2. 類裝載期植入
  3. 動態代理植入

Spring中AOP具體的配置過程,可經過如下途徑:ide

  1. 配置ProxyFactoryBean,顯式設置advisors, advice, target等
  2. 配置AutoProxyCreator,使用定義bean的方式不變,可是從容器中得到的是代理對象

 

最頂層是ProxyConfig是一個數據,這個數據基類爲ProxyFactoryBean這樣的子類提供了配置屬性;post

AdvisedSupport的封裝了Aop對通知和通知器的相關操做,這些操做對於不一樣的Aop的代理對象的生成都是同樣的,this

但對於具體的Aop代理對象的建立,AdvisedSupport把它交給它的子類們去完成;對於ProxyCreatorSupport,spa

能夠將它當作是其子類建立Aop代理對象的一個輔助類;具體的Aop代理對象的生成,根據不一樣的須要,prototype

分別由ProxyFactoryBean、ProxyFactory、AspectJProxyFactory來完成 代理

 

AbstractAutoProxyCreator 實現了BeanPostProcessor,當系統比較複雜或者中須要進行aop織入的bean較多時,

簡單採用ProxyFacotryBean無疑會增長不少工做量,同時因爲要從ProxyFactoryBean得到代理對象,也會使應用

和Spring之間的耦合度增長,這樣的狀況下,自動Aop代理的方式就能發揮它巨大的優點了。 

 

1、AOP對象的生成

1.ProxyFactory是怎樣獲得代理類的

public Object getProxy() {
        return createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }

 

 

 

2.ProxyFactoryBean是怎樣得到代理類的

ProxyFactoryBean是在Spring IoC環境中。

    @Override
    public Object getObject() throws BeansException {
        initializeAdvisorChain(); //初始化通知器
        if (isSingleton()) {
            return getSingletonInstance();//依據定義生成單例的Proxy
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance(); //這裏依據定義生成prototype的Proxy
        }
    }

 

使用示例

 

 

public class SayMehthodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(" method對象:" + invocation.getMethod() );
        System.out.println(" invocation對象:" + invocation);
        return invocation.proceed();
    }
}



public static void proxyFactoryBean(){
    ProxyFactoryBean factory = new ProxyFactoryBean();
    
    //給代理工廠一個原型對象
    factory.setTarget(new Person());
    
    factory.addAdvisors(getAdvisor());
    
    //從代理工廠中獲取一個代理後的對象
    Person p = (Person) factory.getObject();
    p.say();
}

public static void proxyFactory(){
    ProxyFactory factory = new ProxyFactory();
    factory.setTarget(new Person());
    factory.addAdvisors(getAdvisor());

    Person p = (Person) factory.getProxy();
    p.say();
}

private static Advisor getAdvisor(){
    //切點
    JdkRegexpMethodPointcut cut = new JdkRegexpMethodPointcut();
    cut.setPatterns(new String[]{".*run.*",".*say.*"});//能夠配置多個正則表達式

    //通知
    //Advice advice = new SayMehthodInterceptor();
    Advice advice = new CarLinkServiceInterceptor();

    //切面 = 切點 + 通知
    return  new DefaultPointcutAdvisor(cut, advice);

}

 

 

2、實現類比較

1. ProxyFactoryBean 

使用率最高的 proxy 方式, 它經過配置 interceptorNames 屬性決定加入哪些 advisor (method interceptor 將會被自動包裝成 advisor, 下文將描述這個細節), 
注意是 "interceptorNames" 而不是 "interceptors",

緣由是 ProxyFactoryBean 可能返回非 singleton 的 proxy 實例, 而 advisior 可能也是非 singleton 的,

所以不能經過 interceptor reference 來注入 

2. TransactionProxyFactoryBean

特定用於 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是說,

TransactionProxyFactoryBean 永遠沒法返回非 singleton 的 proxy 實例 

若是你須要非 singleton 的 proxy 實例, 請考慮使用 ProxyFactoryBean. 

3. BeanNameAutoProxyCreator

故名思義, 根據 bean name 進行 auto proxy, bean name 的 match 規則參見 org.springframework.util.PatternMatchUtils 

4. DefaultAdvisorAutoProxyCreator

更強大的 auto proxy creator, 強大之處在於它會 cahce 容器中全部註冊的 advisor, 而後搜索容器中全部的 bean , 
若是某個 bean 知足 advisor 中的 Pointcut, 那麼將會被自動代理, 與 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工做

5.InfrastructureAdvisorAutoProxyCreator

只解析spring 自身的 advisor, 用戶自定義的不處理

 

3、org.aopalliance.intercept.MethodInterceptor 如何被包裝成 Advisor 

    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }


    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

 從代碼能夠看到, 若是 adviceObject(也就是 interceptorNames 對應的 bean) 不是 advisor 

而是 MethodInterceptor 或 Advice, 那麼 spring 將其包裝成 DefaultPointcutAdvisor, 

而 DefaultPointcutAdvisor 中定義的 Pointcut 是 TruePointcut .

也就是說, MethodInterceptor 和 Advice 被包裝成的 Advisor 將會匹配容器中的全部 bean,

因此, 永遠不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一個 Advice,

那將會使容器中全部的 bean 被自動代理!!! 此時應該考慮使用 BeanNameAutoProxyCreator

 

 

 

 

 

參考:

網易樂得技術團隊:Spring-SpringMVC父子容器&AOP使用總結

spring aop 代理對象生成

相關文章
相關標籤/搜索