天天看點

bboss aop/ioc依賴注入功能介紹

bboss aop

3.5及後續版本中改進的

ioc依賴注入

功能介紹。

bboss依賴注入支援複雜關系的依賴注入:元件直接自引用(a->a),元件間接自引用(a->b->a),元件間循環依賴引用(a->b->c->d->b)

舉一個簡單的自引用的列子:

<property name="test" class="org.frameworkset.spi.remote.RPCTest" f:selfvar="attr:test"/>

一、新的ioc功能特點

改進後的ioc依賴注入機制支援完整的循環依賴注入功能,并且支援任何層級的對象及對象屬性引用,為了對照refid和直接配置的元件的差別,我們先看一個普通元件的配置方法:

<properties>
	<property name="rpc.test" class="org.frameworkset.spi.remote.RPCTest"/>
</properties>      

refid屬性值的格式執行個體如下:

<property name="test2" refid="attr:test1->test2" />

在介紹refid屬性的各種引用格式及含義之前,我們先看一個完整的執行個體:

<?xml version="1.0" encoding="gbk"?>
<properties>
	<property name="test1" class="org.frameworkset.soa.xblink.Test1">
		<property name="test2" class="org.frameworkset.soa.xblink.Test2">
<!--内部元件test2的test1屬性引用外層元件test1-->
			<property name="test1" refid="attr:test1" />
		</property>
 
		<property name="test3" class="org.frameworkset.soa.xblink.Test3">
<!--内部元件test3的test2屬性引用外部元件test1的屬性test2-->
			<property name="test2" refid="attr:test1->test2" />
		</property>
<!--test4屬性引用外部元件test1,這是一個對象自我引用配置方式-->
		<property name="test4" refid="attr:test1"/>
	</property>
</properties>      

refid屬性的所有格式及含義說明如下:

refid格式                                                                                       含義

1.attr:serviceid                             根據服務辨別引用容器服務元件

2.attr:serviceid[0]                          根據服務辨別及數組下标引用容器服務元件對應的下标為0對應的元素(容器服務元件類型為list,set,array三種類型)

3.attr:serviceid[key]                        根據服務辨別及map key引用容器服務元件對應的索引為key對應的元素(容器服務元件類型為map類型)

4.attr:serviceid{0}                          根據服務辨別及構造函數參數位置下标引用容器服務元件對應的下标為0對應的構造函數參數(容器服務元件為構造函數注入)

5.attr:serviceid->innerattributename         根據服務辨別及服務元件的屬性名稱引用容器服務元件屬性值

6.attr:serviceid->innerattributename[0]      根據服務辨別及服務屬性名稱以及屬性數組下标引用容器服務元件屬性中對應的下标為0對應的元素(容器服務元件類型為list,set,array三種類型)

7.attr:serviceid->innerattributename[key]    根據服務辨別及服務屬性名稱以及map key引用容器服務元件屬性對應的索引為key對應的元素(容器服務元件類型為map類型)

8.attr:serviceid->innerattributename{0}      根據服務辨別及服務屬性名稱對應屬性的造函數參數位置下标引用容器服務元件對應的下标為0對應的構造函數參數(容器服務元件為構造函數注入)

其中屬性的引用是不限制層級的。

下面舉例來說明上述每種情況的使用方法。

二、引用使用詳解

通過在xml配置檔案中配置一個的複雜對象Test1元件來說明IOC的循環依賴功能以及局部屬性引用功能。

涉及的三個對象Test1、Test2、Test3定義如下:

Test1對象:

package org.frameworkset.soa.xblink;

import java.util.List;
import java.util.Map;

public class Test1 {
	Test2 test2;
	Test3 test3;
	Test1 test4;
	Test1 test5;
	Test2 test6;
	Test2 test7;
	Test2 test8;
	Test1 test9;
	Test1 test10;
	Test1 test11;
	Test2 test12;
	Map testmap;
	List testlist;
	Test1[] testarray;
}      

Test2對象:

package org.frameworkset.soa.xblink;

public class Test2 {
	Test1 test1;
	Test3 test3;
}      

Test3對象:

package org.frameworkset.soa.xblink;

public class Test3  implements java.io.Serializable{
	Test2 test2;
}      

看以看出幾個對象之間的引用是錯綜複雜的,基于此我們再來看看test1元件的配置:包括了Test1所有屬性的配置,每個屬性的配置都包含了詳細的含義說明,這些屬性的配置基本涵蓋了bboss ioc依賴注入的所有功能特性,本文中暫不介紹針對構造函數參數的引用功能:

案例一

<?xml version="1.0" encoding="gbk"?>
<properties>
    <!-- 通過test1對應的複雜對象Test1來說明IOC的循環依賴功能以及局部屬性引用功能 -->
	<property name="test1" class="org.frameworkset.soa.xblink.Test1">
		<property name="test2" class="org.frameworkset.soa.xblink.Test2">
		    <!--内部元件test2的test1屬性引用外層元件test1-->		
			<property name="test1" refid="attr:test1" />
			<!--内部元件test2的test3屬性引用外層元件test1的test3屬性-->
			<property name="test3" refid="attr:test1->test3" />
		</property>
		<!--内部元件test3的test2屬性引用外層元件test1的test2屬性-->
		<property name="test3" class="org.frameworkset.soa.xblink.Test3"
			f:test2="attr:test1->test2"/>
		<!--test4屬性直接引用外層元件test1-->
		<property name="test4" refid="attr:test1"/>
		<property name="testmap" >
			<map componentType="bean">
			    <!--Map類型屬性testmap的test4索引對應的值是對外層元件test1引用-->
				<property name="test4" refid="attr:test1"/>
			</map>
		</property>
		<property name="testlist" >
			<list componentType="bean">
			 <!--List類型屬性testlist的第一個值是對外層元件test1引用-->
				<property refid="attr:test1"/>
			</list>
		</property>
		<property name="testarray" >
			<array componentType="org.frameworkset.soa.xblink.Test1">
				<!--數組類型屬性testlist的第一個值是對外層元件test1引用-->
				<property refid="attr:test1"/>
			</array>
		</property>
		<!--test5屬性直接引用外層test1元件的屬性test4-->
		<property name="test5" refid="attr:test1->test4"/>
		<!--test6屬性直接引用外層test1元件的數組屬性testarray的第一個元素對象的test2屬性-->
		<property name="test6" refid="attr:test1->testarray[0]->test2"/>
		<!--test7屬性直接引用外層test1元件的List屬性testlist的第一個元素對象的test2屬性-->
		<property name="test7" refid="attr:test1->testlist[0]->test2"/>
		<!--test8屬性直接引用外層test1元件的Map屬性testmap的key為test4對應的值對象的test2屬性-->
		<property name="test8" refid="attr:test1->testmap[test4]->test2"/>
		<!--test9屬性直接引用外層test1元件的數組屬性testarray的第一個元素對象-->
		<property name="test9" refid="attr:test1->testarray[0]"/>
		<!--test10屬性直接引用外層test1元件的List屬性testlist的第一個元素對象-->
		<property name="test10" refid="attr:test1->testlist[0]"/>
		<!--test11屬性直接引用外層test1元件的Map屬性testmap的key為test4對應的值對象-->
		<property name="test11" refid="attr:test1->testmap[test4]"/>
		<!--test12屬性直接引用外層test1元件的屬性test3對象中的test2屬性-->
		<property name="test12" refid="attr:test1->test3->test2"/>
	</property>
</properties>      

下面看看如何加載上述

配置

并擷取test1對象,然後看看xml-bean互相轉換的

過程

//加載配置檔案,建構一個元件容器對象
		BaseApplicationContext context = DefaultApplicationContext.getApplicationContext("org/frameworkset/soa/xblink/testcontainref.xml");
		//擷取元件test1
		Test1 test1 = context.getTBeanObject("test1",  Test1.class);
		//重新将元件序列化為xml串
		String ss = ObjectSerializable.toXML(test1);
		//将xml串ss轉換為對象test_
		Test1 test1_ =  (Test1)ObjectSerializable.toBean(ss,Test1.class);      

再看看一個包含二維元素引用的示例配置:

<?xml version="1.0" encoding="gbk"?>
<properties>
    <!-- 通過test1對應的複雜對象Test1來說明IOC的循環依賴功能以及局部屬性引用功能 -->
	<property name="test1" class="org.frameworkset.soa.xblink.Test1">
		<property name="test2" class="org.frameworkset.soa.xblink.Test2">
		    <!--内部元件test2的test1屬性引用外層元件test1-->		
			<property name="test1" refid="attr:test1" />
			<!--内部元件test2的test3屬性引用外層元件test1的test3屬性-->
			<property name="test3" refid="attr:test1->test3" />
		</property>
		<!--内部元件test3的test2屬性引用外層元件test1的test2屬性-->
		<property name="test3" class="org.frameworkset.soa.xblink.Test3"
			f:test2="attr:test1->test2"/>
		<!--test4屬性直接引用外層元件test1-->
		<property name="test4" refid="attr:test1"/>
		<property name="testmap" >
			<map componentType="bean">
			    <!--Map類型屬性testmap的test4索引對應的值是對外層元件test1引用-->
				<property name="test4" refid="attr:test1"/>
			</map>
		</property>
		<property name="testlist" >
			<list componentType="bean">
			 <!--List類型屬性testlist的第一個值是對外層元件test1引用-->
				<property refid="attr:test1"/>
			 <!--List類型屬性testlist的第二個值是對外層元件test1的數組屬性testarraybasic的引用-->
				<property refid="attr:test1->testarraybasic"/>
			</list>
		</property>
		<property name="testarray" >
			<array componentType="org.frameworkset.soa.xblink.Test1">
				<!--數組類型屬性testlist的第一個值是對外層元件test1引用-->
				<property refid="attr:test1"/>
				<!--數組類型屬性testlist的第二個值是對外層元件test1的數組屬性testarraybasic的第二個值得引用-->
				<property refid="attr:test1->testarraybasic[1]"/>
			</array>
		</property>
		<!--數組類型屬性testarraybasic用來驗證屬性多元引用功能-->
		<property name="testarraybasic" >
			<array componentType="org.frameworkset.soa.xblink.Test1">
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
			</array>
		</property>
		<!--屬性innerelement用來驗證屬性二維引用功能-->
		<property name="innerelement" refid="attr:test1->testlist[1][0]"/>
		<!--test5屬性直接引用外層test1元件的屬性test4-->
		<property name="test5" refid="attr:test1->test4"/>
		<!--test6屬性直接引用外層test1元件的數組屬性testarray的第一個元素對象的test2屬性-->
		<property name="test6" refid="attr:test1->testarray[0]->test2"/>
		<!--test7屬性直接引用外層test1元件的List屬性testlist的第一個元素對象的test2屬性-->
		<property name="test7" refid="attr:test1->testlist[0]->test2"/>
		<!--test8屬性直接引用外層test1元件的Map屬性testmap的key為test4對應的值對象的test2屬性-->
		<property name="test8" refid="attr:test1->testmap[test4]->test2"/>
		<!--test9屬性直接引用外層test1元件的數組屬性testarray的第一個元素對象-->
		<property name="test9" refid="attr:test1->testarray[0]"/>
		<!--test10屬性直接引用外層test1元件的List屬性testlist的第一個元素對象-->
		<property name="test10" refid="attr:test1->testlist[0]"/>
		<!--test11屬性直接引用外層test1元件的Map屬性testmap的key為test4對應的值對象-->
		<property name="test11" refid="attr:test1->testmap[test4]"/>
		<!--test12屬性直接引用外層test1元件的屬性test3對象中的test2屬性-->
		<property name="test12" refid="attr:test1->test3->test2"/>
	</property>
</properties>      

test1中的屬性innerelement引用了list屬性testlist的第二個元素對應的數組中的第一個資料:

<property name="innerelement" refid="attr:test1->testlist[1][0]"/>

testlist屬性的定義如下:

<property name="testlist" >
			<list componentType="bean">
			 <!--List類型屬性testlist的第一個值是對外層元件test1引用-->
				<property refid="attr:test1"/>
			 <!--List類型屬性testlist的第二個值是對外層元件test1的數組屬性testarraybasic的引用-->
				<property refid="attr:test1->testarraybasic"/>
			</list>
		</property>      

其中的第二個元素,又是對test1中的一個數組屬性testarraybasic的引用:

<property refid="attr:test1->testarraybasic"/>

testarraybasic屬性的定義如下:

<property name="testarraybasic" >
			<array componentType="org.frameworkset.soa.xblink.Test1">
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
				<property class="org.frameworkset.soa.xblink.Test1"/>
			</array>
		</property>