這篇文章主要講解了“怎么使用@Profile”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“怎么使用@Profile”吧!

在惠農(nóng)等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需定制開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),成都營(yíng)銷網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站制作,惠農(nóng)網(wǎng)站建設(shè)費(fèi)用合理。
Environment接口是在容器中抽象集成,應(yīng)用環(huán)境包括兩個(gè)重要的方面:profiles 和 properties。配置文件是一個(gè)命名的bean定義邏輯組,只有在給定的配置文件處于激活狀態(tài)時(shí)才在容器中注冊(cè)。可以將bean分配給配置文件,不管它是用XML定義的還是用注解定義的。與profile文件相關(guān)的環(huán)境對(duì)象的角色是確定哪些profile文件(如果有的話)當(dāng)前是激活的,以及哪些profile文件(如果有的話)在默認(rèn)情況下應(yīng)該是激活的。
Properties幾乎在所有應(yīng)用中扮演一個(gè)重要的角色并且可能來(lái)自于多個(gè)源:屬性文件、JVM系統(tǒng)屬性、系統(tǒng)環(huán)境變量、JNDI、servlet上下文參數(shù)、Properties對(duì)象、Map對(duì)象等等。Environment對(duì)象的角色與properties關(guān)聯(lián)去提供給用戶一個(gè)便利的服務(wù)接口去配置屬性源和解析屬性。
bean定義屬性文件在核心容器中提供一個(gè)機(jī)制,它允許在不同的環(huán)境中注冊(cè)不同bean。環(huán)境這個(gè)詞對(duì)于不同的用戶可能意味著不同的東西,這個(gè)特性可以幫助許多使用場(chǎng)景,包括:
在開發(fā)中針對(duì)內(nèi)存中的數(shù)據(jù)源進(jìn)行工作,而不是在進(jìn)行QA或生產(chǎn)時(shí)從JNDI查找相同的數(shù)據(jù)源。
當(dāng)部署應(yīng)用到執(zhí)行環(huán)境使用注冊(cè)健康基礎(chǔ)設(shè)施
為客戶A和客戶B部署注冊(cè)定制的bean實(shí)現(xiàn)。
在實(shí)踐應(yīng)用中考慮第一個(gè)使用場(chǎng)景,它需要獲取一個(gè)DataSource。在測(cè)試環(huán)境中,配置假設(shè)如下:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("my-schema.sql")
.addScript("my-test-data.sql")
.build();
}現(xiàn)在考慮這個(gè)應(yīng)用怎樣部署到QA或生產(chǎn)環(huán)境,假設(shè)應(yīng)用程序數(shù)據(jù)源注冊(cè)在生成應(yīng)用服務(wù)JNDI目錄。我們的dataSource bean看起來(lái)類似下面清單:
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}問(wèn)題是如何根據(jù)當(dāng)前環(huán)境在使用這兩種變體之間進(jìn)行切換。隨著時(shí)間的流逝,Spring用戶已經(jīng)設(shè)計(jì)出多種方法來(lái)完成此任務(wù),通常依賴系統(tǒng)環(huán)境變量和包含$ {placeholder}占位符的XML <import/>語(yǔ)句的組合,這些語(yǔ)句根據(jù)值解析為正確的配置文件路徑環(huán)境變量。Bean定義配置文件是一項(xiàng)核心容器功能,可解決此問(wèn)題。
如果我們概括前面環(huán)境特定的bean定義示例中所示的用例,我們最終需要在特定上下文中注冊(cè)特定的bean定義,而不是在其他上下文中注冊(cè)。可以這樣說(shuō),你希望在情形A中注冊(cè)bean定義的某個(gè)配置文件,而在情形B中注冊(cè)另一個(gè)配置文件。我們開始更新配置以反映這種需求。
使用@Profile
@Profile注解允許你去指明哪些組件適合去注冊(cè),當(dāng)一個(gè)或多個(gè)指定profile處于激活狀態(tài)時(shí)。使用我們前面的例子,我們可以重寫dataSource配置如下:
@Configuration
@Profile("development")
public class StandaloneDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}如前所述,對(duì)于
@Bean方法,你典型的選擇使用編程式的JNDI查找,通過(guò)使用Spring的JndiTemplate/JndiLocatorDelegate幫助類或直接使用前面展示的JNDIInitialContext,而不是使用JndiObjectFactoryBean變體,這將迫使你將返回類型聲明為FactoryBean類型。
配置文件字符串可能包含一個(gè)簡(jiǎn)單的配置名稱(例如,production)或一個(gè)配置表達(dá)式。一個(gè)配置表達(dá)式允許更復(fù)雜的配置邏輯去表達(dá)(例如,production & us-east),下面的操作符在profile表達(dá)式中是被支持的:
!:邏輯非
&:邏輯與
|:邏輯或
你不能混合
&和!操作符而不使用括號(hào)。例如,production & us-east | eu-central是無(wú)效表達(dá)式。它必須被表達(dá)類似production & (us-east | eu-central)。
你可以使用@Profile作為一個(gè)元數(shù)據(jù)注解去創(chuàng)建你自定義的注解。以下示例定義了一個(gè)自定義@Production注解,你可以將其用作@Profile(“ production”)的替代。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("production")
public @interface Production {
}如果
@Configuration類被標(biāo)注@Profile,所有的@Bean方法和@Import注解關(guān)聯(lián)的類都將被繞過(guò),除非一個(gè)或多個(gè)指定的配置文件被激活。如果@Component或@Configuration類被標(biāo)記@Profile({"p1", "p2"}),這個(gè)類不會(huì)被注冊(cè)或處理除非配置文件p1或p2被激活。如果給的配置前綴是NOT操作符(!),注解元素僅僅在配置文件沒(méi)有被激活時(shí)被注冊(cè)。例如,@Profile({"p1", "!p2"}),如果配置p1被激活或者配置p2沒(méi)有被激活時(shí)注冊(cè)才會(huì)發(fā)生。
@Profile也可以被聲明在方法級(jí)別去包含一個(gè)特定的配置bean類(例如,用于特定bean的替代),類似下面例子展示:
@Configuration
public class AppConfig {
@Bean("dataSource")
@Profile("development") //1
public DataSource standaloneDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
@Bean("dataSource")
@Profile("production") //2
public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}standaloneDataSource方法僅僅在development配置中有效
jndiDataSource方法僅僅在production配置中有效
對(duì)于
@Bean方法上的@Profile,可以應(yīng)用一個(gè)特殊的場(chǎng)景:在重載相同Java方法名的@Bean方法(類似于構(gòu)造函數(shù)重載)的情況下,需要一致地在所有重載方法上聲明@Profile條件。如果條件不一致,則只有重載方法中第一個(gè)聲明的條件重要。因此,@Profile不能被使用去選擇具有特定參數(shù)簽名重載方法。在創(chuàng)建時(shí),同一bean的所有工廠方法之間的解析都遵循Spring的構(gòu)造函數(shù)解析方法。如果你想去定義不同配置條件的bean,使用不同的Java方法名稱,通過(guò)使用
@Beanname屬性指向相同名稱的bean,類似前面展示例子。如果參數(shù)前面都相同(例如,所有的變體有無(wú)參構(gòu)造函數(shù)),這是在一個(gè)有效的Java類中表示這種安排的唯一方法(因?yàn)橹荒苡幸粋€(gè)具有特定名稱和參數(shù)簽名的方法)。
XML bean定義配置文件
XML對(duì)應(yīng)項(xiàng)是<beans>元素的profile屬性。我們前面的相同配置能被重寫在兩個(gè)XML文件中,類似下面:
<beans profile="development" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="..."> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/> <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/> </jdbc:embedded-database> </beans>
<beans profile="production" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="..."> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans>
也可以避免在同一文件中拆分和嵌套<beans/>元素,如以下示例所示:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="..."> <!-- other bean definitions --> <beans profile="development"> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/> <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/> </jdbc:embedded-database> </beans> <beans profile="production"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans> </beans>
spring-bean.xsd已被限制為僅允許這些元素作為文件中的最后一個(gè)。這應(yīng)該有助于提供靈活性,而不會(huì)在XML文件中引起混亂。
XML對(duì)應(yīng)項(xiàng)不支持前面描述的配置文件表達(dá)式:然而,它可能通過(guò)
!操作符否定一個(gè)配置文件。它也可能通過(guò)嵌入配置文件應(yīng)用邏輯and,類型下面例子顯示:<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="..."> <!-- other bean definitions --> <beans profile="production"> <beans profile="us-east"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans> </beans> </beans>在前面的例子中,如果
production和us-east配置都被激活,則dataSourcebean被暴露。
激活profile
現(xiàn)在我們已經(jīng)更新了配置文件,我們?nèi)匀恍枰甘維pring哪一個(gè)配置文件激活。如果我們已經(jīng)啟動(dòng)了我們的應(yīng)用程序,我們將看到一個(gè)NoSuchBeanDefinitionException拋出,因?yàn)槿萜鞑荒苷业矫Q為dataSource的bean。
可以通過(guò)多種方式來(lái)激活配置文件,但最直接的方法是可通過(guò)ApplicationContext獲得的Environment API以編程方式進(jìn)行配置。下面例子展示怎樣去做:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();此外,你也可以聲明式地激活配置文件通過(guò)spring.profiles.active屬性,也可通過(guò)系統(tǒng)環(huán)境變量、JVM屬性、在web.xml中servlet上下文參數(shù),甚至作為JNDI中的條目(查看PropertySource抽象)。在集成測(cè)試中,激活配置文件可以通過(guò)使用@ActiveProfiles聲明在spring-test模塊(查看上下文配置通過(guò)環(huán)境配置文件)。
請(qǐng)注意,配置文件不是非此即彼的命題。你可以一次性激活多個(gè)配置文件。編程式地,你可以提供多個(gè)配置文件名稱給setActiveProfiles()方法,它可以接受String… 可變參數(shù)。下面例子激活多個(gè)配置文件:
ctx.getEnvironment().setActiveProfiles("profile1", "profile2");聲明式地,spring.profiles.active可以接收配置名稱逗號(hào)分隔列表,類似下面例子展示:
-Dspring.profiles.active="profile1,profile2"
默認(rèn)profile
默認(rèn)配置文件表示默認(rèn)情況下啟用的配置文件。考慮下面例子:
@Configuration
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}如果沒(méi)有profile被激活,dataSource實(shí)例被創(chuàng)建。你可以看到這種方式提供一個(gè)默認(rèn)的定義為一個(gè)或多個(gè)bean。如果任何profile被激活,這個(gè)默認(rèn)profile不被使用。
你可以通過(guò)在Environment上使用setDefaultProfiles()改變默認(rèn)profile名稱或者,聲明式地,通過(guò)使用spring.profiles.default屬性。
PropertySource抽象
Spring的Environment抽象提供了可配置屬性源層次結(jié)構(gòu)上的搜索操作。考慮下面清單:
ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
boolean containsMyProperty = env.containsProperty("my-property");
System.out.println("Does my environment contain the 'my-property' property? " + containsMyProperty);在前面的片段中,我們看到一個(gè)高級(jí)別的詢問(wèn)Spring的方式,是否my-property屬性在當(dāng)前環(huán)境中被定義:去回答這個(gè)問(wèn)題,Environment對(duì)象執(zhí)行搜索PropertySource 集合對(duì)象。PropertySource是一個(gè)簡(jiǎn)單key-value對(duì)源的抽象,并且Spring的StandardEnvironment被配置兩個(gè)PropertySource 對(duì)象,一個(gè)描述JVM系統(tǒng)(System.getProperties())屬性集合另一個(gè)描述系統(tǒng)環(huán)境變量集合(System.getenv())。
這些默認(rèn)的屬性源適用
StandardEnvironment,為在獨(dú)立的應(yīng)用中使用。StandardServletEnvironment是通過(guò)附加默認(rèn)屬性源填充,包括servlet配置和servlet上下文參數(shù)。它可以選擇啟用JndiPropertySource。查看javadock詳情。
具體地說(shuō),當(dāng)你使用StandardEnvironment時(shí),如果my-property系統(tǒng)屬性或my-property環(huán)境變量在運(yùn)行時(shí)被描述,調(diào)用env.containsProperty("my-property")方法將返回true。
執(zhí)行的搜索是分層的,默認(rèn)情況,系統(tǒng)屬性優(yōu)先級(jí)高于環(huán)境變量。因此,如果
my-property屬性在兩個(gè)地方被設(shè)置,在調(diào)用env.getProperty("my-property")時(shí),系統(tǒng)屬性值將被返回。請(qǐng)注意,屬性值不會(huì)合并,而是會(huì)被前面的值完全覆蓋。對(duì)于通用的
StandardServletEnvironment,完整的層次結(jié)構(gòu)如下,優(yōu)先級(jí)最高的條目位于頂部:
1.ServletConfig參數(shù)(如果使用的-例如,如果是DispatcherServlet上下文)
2.ServletContext參數(shù)(web.xml 上下文參數(shù))3.JNDI 環(huán)境變量(
java:comp/env/)4.JVM系統(tǒng)參數(shù)(-D 命令行參數(shù))
5.JVM系統(tǒng)變量(操作系統(tǒng)環(huán)境變量)
最重要地,整個(gè)機(jī)制是可配置的。也許你有一個(gè)自定義的屬性源,你想整合到此搜索中。這樣做,實(shí)現(xiàn)和實(shí)例化你的PropertySource并且添加到當(dāng)前的Environment PropertySources集合中。下面例子展示怎樣去做:
ConfigurableApplicationContext ctx = new GenericApplicationContext(); MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); sources.addFirst(new MyPropertySource());
在前面的代碼中,MyPropertySource被添加到最高索引優(yōu)先級(jí)中。如果它包含my-property屬性,則會(huì)檢測(cè)到并返回該屬性,從而支持任何其他PropertySource中的my-property屬性。MutablePropertySourcesAPI暴露了一些方法,這些方法允許去精確操作屬性源集合。
@PropertySource
@PropertySource注解提供一個(gè)便捷的和陳述式的機(jī)制去添加PropertySource到Spring的Environment中。
給定一個(gè)名叫app.properties文件,它包含健值對(duì)testbean.name=myTestBean,下面的@Configuration類使用@PropertySource,以這種方式調(diào)用testBean.getName()并返回myTestBean:
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}@PropertySource資源位置中出現(xiàn)的任何${}占位符都將根據(jù)已經(jīng)在環(huán)境中注冊(cè)的屬性源集進(jìn)行解析,如下面的示例所示:
@Configuration
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}假設(shè)my.placeholder在一個(gè)已經(jīng)被注冊(cè)的屬性源中被描述(例如,系統(tǒng)屬性或環(huán)境變量),則占位符被解析為對(duì)應(yīng)值。如果沒(méi)有,則使用一個(gè)默認(rèn)值default/path。如果沒(méi)有指定默認(rèn)值并且屬性不能被解析,一個(gè)IllegalArgumentException被拋出。
根據(jù)Java8約定,
@PropertySource注解是可以重復(fù)的。然而,所有的@PropertySource注解需要在相同等級(jí)被聲明,要么直接地在配置類上,要么作為元數(shù)據(jù)注解在相同自定義注解中。不建議將直接注釋和元注釋混合使用,因?yàn)橹苯幼⑨寱?huì)有效地覆蓋元注釋。
參考代碼:
com.liyong.ioccontainer.starter.EnvironmentIocContainer
在以前,元素中占位符的值只能根據(jù)JVM系統(tǒng)屬性或環(huán)境變量來(lái)解析。現(xiàn)在情況已經(jīng)不同了。因?yàn)?code>Environment抽象已經(jīng)集成到容器,很容易通過(guò)它來(lái)路由占位符的解析。這意味著你可以按照自己喜歡的任何方式配置解析過(guò)程。你可以更改搜索系統(tǒng)屬性和環(huán)境變量的優(yōu)先級(jí),也可以完全刪除它們。你還可以適當(dāng)?shù)貙⒛阕约旱膶傩栽刺砑拥浇M合中。
具體地說(shuō),不論在何處定義customer屬性,只要在環(huán)境中可用,以下語(yǔ)句就可以工作:
<beans>
<import resource="com/bank/service/${customer}-config.xml"/>
</beans>感謝各位的閱讀,以上就是“怎么使用@Profile”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)怎么使用@Profile這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
分享文章:怎么使用@Profile
本文鏈接:http://chinadenli.net/article38/gesipp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、定制開發(fā)、面包屑導(dǎo)航、微信公眾號(hào)、、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)