這篇文章主要介紹了Spring Java-based容器配置的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
作為一家“創(chuàng)意+整合+營銷”的成都網(wǎng)站建設(shè)機(jī)構(gòu),我們在業(yè)內(nèi)良好的客戶口碑。成都創(chuàng)新互聯(lián)提供從前期的網(wǎng)站品牌分析策劃、網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、網(wǎng)站制作、創(chuàng)意表現(xiàn)、網(wǎng)頁制作、系統(tǒng)開發(fā)以及后續(xù)網(wǎng)站營銷運(yùn)營等一系列服務(wù),幫助企業(yè)打造創(chuàng)新的互聯(lián)網(wǎng)品牌經(jīng)營模式與有效的網(wǎng)絡(luò)營銷方法,創(chuàng)造更大的價(jià)值。裝Java-based的配置
使用 @Import 注解
跟在Spring XML文件中使用<import>元素添加模塊化的配置類似,@Import注解允許你加載其他配置類中的@Bean定義:
@Configuration public class ConfigA { @Bean public A a() { return new A(); } } @Configuration @Import(ConfigA.class) public class ConfigB { @Bean public B b() { return new B(); } }
組現(xiàn)在,當(dāng)實(shí)例化上下文時(shí),你只需要顯式的指定ConfigB,而不需要既提供ConfigA.class,又提供ConfigB.class:
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); // now both beans A and B will be available... A a = ctx.getBean(A.class); B b = ctx.getBean(B.class); }
這種方式簡化了容器的初始化,因?yàn)橹恍枰幚硪粋€類,而不是讓開發(fā)者記住構(gòu)造期間的大量@Configuration類。
導(dǎo)入@Bean的依賴注入
上面的示例可以工作,但太簡單。在大多數(shù)實(shí)際的場景中,beans會依賴另一個跨配置類的bean。當(dāng)使用XML時(shí),這不是問題,因?yàn)椴簧婕暗骄幾g,其中一個bean只需要聲明ref="someBean",剩下的交給Spring在容器初始化期間處理即可。當(dāng)然,當(dāng)使用@Configuration類時(shí),Java編譯器對配置模式產(chǎn)生一些限制,對其他beans的引用必須是合法的java語法。
幸運(yùn)的是,解決該問題是很容易的。正如我們已經(jīng)討論的,@Bean可以有任意多個用來描述bean依賴的參數(shù)。讓我們探討一個更現(xiàn)實(shí)的場景,在這里將使用一些彼此依賴的@Configuration類:
@Configuration public class ServiceConfig { @Bean public TransferService transferService(AccountRepository accountRepository) { return new TransferServiceImpl(accountRepository); } } @Configuration public class RepositoryConfig { @Bean public AccountRepository accountRepository(DataSource dataSource) { return new JdbcAccountRepository(dataSource); } } @Configuration @Import({ ServiceConfig.class, RepositoryConfig.class } ) public class SystemTestConfig { @Bean public DataSource dataSource() { // return new DataSource } } public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); // everything wires up across configuration classes... TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, "A123", "C456"); }
這里有另外的方法可以達(dá)到相同的效果。記住,@Configuration根本上只是容器中的另一個bean-這意味著它們可以像其他bean那樣充分利用@Autowired注入元數(shù)據(jù)。
注: 確保以這種方式注入的都是簡單類型的。@Configuration類在容器初始化時(shí)被處理的相當(dāng)早,用這種方式強(qiáng)制注入依賴可能導(dǎo)致無法預(yù)料地過早初始化問題。只要有可能就采用上面示例中基于參數(shù)的注入方式。
@Configuration public class ServiceConfig { @Autowired private AccountRepository accountRepository; @Bean public TransferService transferService() { return new TransferServiceImpl(accountRepository); } } @Configuration public class RepositoryConfig { @Autowired private DataSource dataSource; @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(dataSource); } } @Configuration @Import({ ServiceConfig.class, RepositoryConfig.class } ) public class SystemTestConfig { @Bean public DataSource dataSource() { // return new DataSource } } public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); // everything wires up across configuration classes... TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, "A123", "C456"); }
在上面的示例中,使用@Autowired工作的很好,并且提供了想要的模塊化,但要確切地指明自動注入的bean定義在哪聲明依舊有點(diǎn)模糊。例如,一個開發(fā)者正在查看ServiceConfig,那你怎么準(zhǔn)確地知道@Autowired AccountRepository bean在哪聲明的?在代碼中并不明確,不過有時(shí)候這樣就行。記著Spring Tool Suite可以提供渲染圖的工具,這些圖展示了Spring Bean之間是怎么連起來的-這可能是你需要的。同時(shí),你的Java IDE可以輕松的找到所有聲明和使用AccountRepository類型的bean,并為你快速展現(xiàn)返回該類型的@Bean方法位置。
如果你不能接受這種模糊性,并希望在你的IDE中可以從一個@Configuration類導(dǎo)航到另一個,那就考慮注入配置類本身:
@Configuration public class ServiceConfig { @Autowired private RepositoryConfig repositoryConfig; @Bean public TransferService transferService() { // navigate 'through' the config class to the @Bean method! return new TransferServiceImpl(repositoryConfig.accountRepository()); } }
在上面的解決方案中,我們可以很明確地知道AccountRepository定義的地方。然而,ServiceConfig現(xiàn)在緊緊地跟RepositoryConfig耦合了。這就是權(quán)衡。緊耦合在某種程度上可以通過使用基于接口或抽象類的@Configuration類來減輕??紤]以下內(nèi)容:
@Configuration public class ServiceConfig { @Autowired private RepositoryConfig repositoryConfig; @Bean public TransferService transferService() { return new TransferServiceImpl(repositoryConfig.accountRepository()); } } @Configuration public interface RepositoryConfig { @Bean AccountRepository accountRepository(); } @Configuration public class DefaultRepositoryConfig implements RepositoryConfig { @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(...); } } @Configuration @Import({ ServiceConfig.class, DefaultRepositoryConfig.class } ) // import the concrete config! public class SystemTestConfig { @Bean public DataSource dataSource() { // return DataSource } } public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, "A123", "C456"); }
現(xiàn)在,ServiceConfig跟具體的DefaultRepositoryConfig類是松耦合的關(guān)系,并且內(nèi)嵌的IDE工具依舊有用:它很容易為開發(fā)者獲取RepositoryConfig實(shí)現(xiàn)的類型層次。采用這種方式,導(dǎo)航@Configuration和它們的依賴就變得跟平常處理基于接口的代碼導(dǎo)航?jīng)]區(qū)別了。
有條件的包含@Configuration類或@Beans
基于任意的系統(tǒng)狀態(tài),有條件地禁用一個完整的@Configuration類,甚至單獨(dú)的@Bean方法通常是很有用的。一個常見的示例是,當(dāng)一個特定的profile在Spring Environment中啟用時(shí),使用@Profile注解激活beans。
@Profile注解實(shí)際上實(shí)現(xiàn)了一個非常靈活的注解:@Conditional。@Conditional注解意味著在注冊@Bean之前,必須先咨詢指定的org.springframework.context.annotation.Condition實(shí)現(xiàn)。
Condition接口的實(shí)現(xiàn)者只需簡單地提供一個返回true或false的matches(…)方法。例如,下面是@Profile注解采用的Condition實(shí)現(xiàn):
@Override public Boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { // Read the @Profile annotation attributes MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) { for (Object value : attrs.get("value")) { if (context.getEnvironment().acceptsProfiles(((String[]) value))) { return true; } } return false; } } return true; }
具體參考@Conditional javadocs。
結(jié)合Java和XML配置
Spring @Configuration類支持目的不是想要100%的替換Spring XML。一些設(shè)施,比如Spring XML命名空間仍舊是配置容器的完美方式。在XML很方便或必須的情況下,你有個選擇:采用”XML為中心”的方式實(shí)例化容器,比如ClassPathXmlApplicationContext,或使用AnnotationConfigApplicationContext以”Java為中心”的方式,并使用@ImportResource注解導(dǎo)入需要的XML。
在以”XML為中心”的情況下使用@Configuration類
從XML啟動Spring容器,以特設(shè)模式包含@Configuration類可能是個更可選的方式。例如,在一個已經(jīng)存在的使用Spring XML的大型代碼庫中,遵循按需原則創(chuàng)建@Configuration,并從現(xiàn)有的XML文件中包括它們是非常容易的。下面你將找到在這樣的”XML為中心”的解決方案中使用@Configuration類的可選項(xiàng)。
記著@Configuration類本質(zhì)上只是容器中的bean定義。在下面的示例中,我們創(chuàng)建了一個名稱為AppConfig的@Configuration類,并將它作為<bean/>定義包含到system-test-config.xml中。因?yàn)?lt;context:annotation-config/>是開啟的,容器將會識別@Configuration注解,并正確地處理AppConfig中聲明的@Bean方法。
@Configuration public class AppConfig { @Autowired private DataSource dataSource; @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(dataSource); } @Bean public TransferService transferService() { return new TransferService(accountRepository()); } }
ystem-test-config.xml如下:
<beans> <!-- enable processing of annotations such as @Autowired and @Configuration --> <context:annotation-config/> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> <bean class="com.acme.AppConfig"/> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
jdbc.properties如下:
jdbc.properties jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa jdbc.password=
main方法如下:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); TransferService transferService = ctx.getBean(TransferService.class); // ... }
注: 在上面的system-test-config.xml中,AppConfig<bean/>沒有聲明一個id元素。如果沒有bean引用它,那就沒有必要指定id元素,否則就要通過name從容器獲取bean(name對應(yīng)bean定義中聲明的id)。DataSource也一樣-它只是通過類型自動注入(autowired by type),所以并不需要顯式的分配一個bean id。
由于@Configuration被@Component元注解了(被注解注解,很拗口),所以被@Configuration注解的類自動成為組件掃描(component scanning)的候選者。同樣使用上面的場景,我們可以重新定義system-test-config.xml來充分利用組件掃描。注意在這個示例中,我們不需要明確聲明<context:annotation-config/>,因?yàn)?lt;context:component-scan/>啟用了同樣的功能。
system-test-config.xml如下:
<beans> <!-- picks up and registers AppConfig as a bean definition --> <context:component-scan base-package="com.acme"/> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
在@Configuration”類為中心”的情況下使用@ImportResourcedaoru導(dǎo)入XML
在將@Configuration類作為配置容器的主要機(jī)制的應(yīng)用中,仍舊存在對XML的需求。在那些場景中,可以使用@ImportResource,并定義所需的XML。這樣做可以實(shí)現(xiàn)以”Java為中心”的方式配置容器,并保留最低限度的XML。
@Configuration @ImportResource("classpath:/com/acme/properties-config.xml") public class AppConfig { @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource() { return new DriverManagerDataSource(url, username, password); } }
properties-config.xml如下:
<beans> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> </beans>
jdbc.properties如下:
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa jdbc.password=
main方法如下:
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); TransferService transferService = ctx.getBean(TransferService.class); // ... }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Spring Java-based容器配置的示例分析”這篇文章對大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
當(dāng)前標(biāo)題:SpringJava-based容器配置的示例分析-創(chuàng)新互聯(lián)
URL網(wǎng)址:http://muchs.cn/article16/icogg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、商城網(wǎng)站、定制網(wǎng)站、網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容