spring-aop組件詳解——TargetSource目標源

        TargetSource(目標源)是被代理的target(目標對象)實例的來源。TargetSource被用於獲取當前MethodInvocation(方法調用)所須要的target(目標對象),這個target經過反射的方式被調用(如:method.invode(target,args))。換句話說,proxy(代理對象)代理的不是target,而是TargetSource,這點很是重要!!!java

        那麼問題來了:爲何SpringAOP代理不直接代理target,而須要經過代理TargetSource(target的來源,其內部持有target),間接代理target呢?spring

        一般狀況下,一個proxy(代理對象)只能代理一個target,每次方法調用的目標也是惟一固定的target。可是,若是讓proxy代理TargetSource,可使得每次方法調用的target實例都不一樣(固然也能夠相同,這取決於TargetSource實現)。這種機制使得方法調用變得靈活,能夠擴展出不少高級功能,如:target pool(目標對象池)、hot swap(運行時目標對象熱替換),等等。app

        接下來要說的另一點,可能會顛覆你的既有認知:TargetSource組件自己與SpringIoC容器無關,換句話說,target的生命週期不必定是受spring容器管理的,咱們以往的XML中的AOP配置,只是對受容器管理的bean而言的,咱們固然能夠手動建立一個target,同時使用Spring的AOP框架(而不使用IoC容器)。Demo以下:框架

// 首先定義一個被代理的目標類
public class TargetBean {
    // 此方法演示使用
	public void show() {
		System.out.println("show");
	}
}
// 接下來是建立代理對象的過程
public class AOPDemo {

	public static void main(String[] args) {
		TargetBean target = new TargetBean();
		TargetSource targetSource = new SingletonTargetSource(target);
		// 使用SpringAOP框架的代理工廠直接建立代理對象
		TargetBean proxy = (TargetBean) ProxyFactory.getProxy(targetSource);
        // 這裏會在控制檯打印:com.lixin.aopdemo.TargetBean$$EnhancerBySpringCGLIB$$767606b3
		System.out.println(proxy.getClass().getName());
	}

}

        這個demo只是建立target的代理對象,並無添加任何加強邏輯。,從輸出能夠看到該目標類已經被CGLIB加強。整個代理過程十分簡單,沒有使用任何BeanFactory或ApplicationContext同樣能夠完成代理。ide

TargetSource功能定義以下:post

public interface TargetSource extends TargetClassAware {

	/**
	 * 返回當前目標源的目標類型。
	 * 能夠返回null值,如:EmptyTargetSource(未知類會使用這個目標源)
	 */
	@Override
	Class<?> getTargetClass();


	/**
	 * 當前目標源是不是靜態的。
	 * 若是爲false,則每次方法調用結束後會調用releaseTarget()釋放目標對象.
	 * 若是爲true,則目標對象不可變,也就不必釋放了。
	 * @return
	 */
	boolean isStatic();

	/**
	 * 獲取一個目標對象。
	 * 在每次MethodInvocation方法調用執行以前獲取。
	 * @return
	 * @throws Exception
	 */
	Object getTarget() throws Exception;

	/**
	 * 釋放指定的目標對象。
	 * @param target
	 * @throws Exception
	 */
	void releaseTarget(Object target) throws Exception;

}

TargetSource組件體系圖以下:spa

TargetSource包含4個簡單實現和3大類實現。prototype

    四個簡單實現包括:線程

  1. EmptyTargetSource:
    靜態目標源,當不存在target目標對象,或者甚至連targetClass目標類都不存在(或未知)時,使用此類實例。
  2. HotSwappableTargetSource:
    動態目標源,支持熱替換的目標源,支持spring應用運行時替換目標對象。
  3. JndiObjectTargetSource:
    spring對JNDI管理bean的支持,static屬性可配置。
  4. SingletonTargetSource:
    靜態目標源,單例目標源。Spring的AOP框架默認爲受IoC容器管理的bean建立此目標源。換句話說,SingletonTargetSource、proxy與目標bean三者的聲明週期均相同。若是bean被配置爲prototype,則spring會在每次getBean時建立新的SingletonTargetSource實例。

      三大類實現包括:代理

  1. AbstractBeanFactoryBasedTargetSource:
    此類目標源基於IoC容器實現,也就是說target目標對象能夠經過beanName從容器中獲取。此類又擴展出:
    (1)SimpleBeanTargetSource:簡單實現,直接調用getBean從容器獲取目標對象;
    (2)LazyInitTargetSource:延遲初始化目標源,子類可重寫postProcessTargetObject方法後置處理目標對象;
    (3)AbstractPrototypeBasedTargetSource:原型bean目標源,此抽象類可確保beanName對應的bean的scope屬性爲prototype。其子類作了簡單原型、池化原型、線程隔離原型這3種實現。
  2. AbstractRefreshableTargetSource:
    可刷新的目標源。此類實現可根據配置的刷新延遲時間,在每次獲取目標對象時自動刷新目標對象。
  3. AbstractLazyCreationTargetSource:
    此類實如今調用getTarget()獲取時才建立目標對象。

        總結一下,本文詳解了什麼是TargetSource,它的做用是什麼,以及該接口的各類實現。最後提醒一下:SpringAOP的自動代理(*AutoProxyCreator),只會爲受SpringIoC容器管理的bean建立SingletonTargetSource。其餘實現類均在手動代理時按需使用。

相關文章
相關標籤/搜索