關(guān)于@Bean的使用方式
@Bean是一個方法級別上的注解,主要用在@Configuration注解的類里,也可以用在@Component注解的類里。
目的是創(chuàng)建一個類。當spring需要創(chuàng)建指定的一個類時會調(diào)用這個注解(@Bean)的方法。
一個對象
@Data @AllArgsConstructor @NoArgsConstructor public class Info { ? ? String name; ? ? int age; }
就如同在在xml配置中添加一個類的配置。這樣spring在自動創(chuàng)建這個類時會調(diào)用配置的方法。
<bean id="info" class="zhong.test.springbootdemo.usultestdemo.demo.Info"> ?? ?<property name="name" value="sjl"/> ? ? <property name="age" value="18"/> </bean>
SprignBoot中 @Bean 完美的替換了了上面的這種在xml中配置的方法。使用以下方法就能讓spring在需要自動創(chuàng)建Info對象時,自動調(diào)用這個方法。
@Configuration public class BeanInit { ? ? /** ? ? ?* 測試@Bean的作用 ? ? ?*/ ? ? @Bean(name = "info") ? ? public Info getInfo(){ ? ? ? ? return new Info("gfagduis", 2343); ? ? } ? ? @Bean(name = "info1") ? ? public Info getInfo1(){ ? ? ? ? return new Info("gfagdufasfdfdais", 2343); ? ? } }
獲取這個類的方法
1、AnnotationConfigApplicationContext 類獲取
@Component public class BeanTest implements CommandLineRunner { ? ? private void getBean(){ ? ? ? ? ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInit.class); ? ? ? ? Info info1= ctx.getBean("info",Info.class); ? ? ? ? System.out.println(info1); ? ? } ? ? @Override ? ? public void run(String... args) throws Exception { ? ? ? ? System.out.println(">>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<"); ? ? ? ? getBean(); ? ? } }
2、在spring自動創(chuàng)建的類中
在構(gòu)造方法中設(shè)置這個值,這樣spring就會調(diào)用該類的創(chuàng)建方法來獲取這個初始化的類。
@Component public class BeanTest implements CommandLineRunner { ? ? private Info info; ?? ?/** ?? ? *spring創(chuàng)建BeanTest對象時會調(diào)用這個構(gòu)造函數(shù)。參數(shù)是info1,所以會調(diào)用 @Bean(name = "info1") 注釋的方法 ?? ? * ?? ? */ ? ? public BeanTest (Info info1){ ? ? ? ? this.info = info1; ? ? } ? ?? ? ?private void getBean2(){ ? ? ? ? System.out.println(info); ? ? } ? ? @Override ? ? public void run(String... args) throws Exception { ? ? ? ? System.out.println(">>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<"); ? ? ? ? getBean2(); ? ? } }
在構(gòu)造函數(shù)中 BeanTest (Info info1) 參數(shù)的名稱是info1.所以就調(diào)用 @Bean(name = “info1”) 的方法來獲取初始化對象。
結(jié)果如下:
>>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<
Info(name=gfagdufasfdfdais, age=2343)
同時也是支持多別名配置的 例如:
? ? @Bean(name = { "info12", "info3", "info3" }) ? ? public Info getInfo2(){ ? ? ? ? return new Info("gfa4361783ais", 2343); ? ? }
測試一下
@Component public class BeanTest implements CommandLineRunner { ? ? private Info info; ? ? private Info info1; ? ? private Info info2; ?? ?/** ?? ? *spring創(chuàng)建BeanTest對象時會調(diào)用這個構(gòu)造函數(shù)。參數(shù)是info1,所以會調(diào)用 @Bean(name = "info1") 注釋的方法 ?? ? * ?? ? */ ? ? public BeanTest (Info info1, Info info2, Info info3){ ? ? ? ? this.info = info1; ? ? ? ? this.info1 = info2; ? ? ? ? this.info2 = info3; ? ? } ? ?? ? ?private void getBean2(){ ? ? ? ? System.out.println(info); ? ? ? ? System.out.println(info1); ? ? ? ? System.out.println(info2); ? ? } ? ? @Override ? ? public void run(String... args) throws Exception { ? ? ? ? System.out.println(">>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<"); ? ? ? ? getBean2(); ? ? } }
結(jié)果如下
>>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<
Info(name=gfagdufasfdfdais, age=2343)
Info(name=gfa4361783ais, age=2343)
Info(name=gfa4361783ais, age=2343)
當然也可以使用 Qualifier(“xxx”) 來指定 @Bean(name = “xxx”) 中的xxx就可以調(diào)用對應(yīng)的方法。
3、使用 @Autowired 注解獲取變量
如果有多個初始化方法,則會根據(jù)變量名稱來獲取。
在初始化類中建立以下多個初始方法
?@Configuration public class BeanInit { ? ? /** ? ? ?* 測試@Bean的作用 ? ? ?*/ ? ? @Bean/*(initMethod = "init")*/ ? ? public Info getInfo(){ ? ? ? ? System.out.println("進入方法"); ? ? ? ? Info info = new Info("gfagduis", 2343); ? ? ? ? System.out.println("結(jié)束方法"); ? ? ? ? return info; ? ? } ? ? @Bean(name = "info1") ? ? public Info getInfo1(){ ? ? ? ? return new Info("gfagdufasfdfdais", 2343); ? ? } ? ? @Bean(name = { "info2", "info3", "info3" }) ? ? public Info getInfo2(){ ? ? ? ? return new Info("gfa4361783ais", 2343); ? ? } ? ? @Bean ? ? public Info info(){ ? ? ? ? return new Info("gfsdfadsfad4361783ais", 23143); ? ? }
然后在測試方法中分別用 @Autowired注釋Info類來獲取對應(yīng)的對象
@Component public class BeanTest implements CommandLineRunner { ? ? //private Info info; ? ? @Autowired ? ? private Info getInfo; ? ? @Autowired ? ? private Info info1; ? ? @Autowired ? ? private Info info3; ? ? @Autowired ? ? private Info info; ? ? /*public BeanTest (Info info){ ? ? ? ? this.info = info; ? ? }*/ ? ? private void getBean(){ ? ? ? ? /*ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInit.class); ? ? ? ? Info person = ctx.getBean("info",Info.class); ? ? ? ? System.out.println(person);*/ ? ? ? ? System.out.println(getInfo); ? ? ? ? System.out.println(info1); ? ? ? ? System.out.println(info3); ? ? ? ? System.out.println(info); ? ? } ? ? @Override ? ? public void run(String... args) throws Exception { ? ? ? ? System.out.println(">>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<"); ? ? ? ? getBean(); ? ? } }
測試結(jié)果如下:
>>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<
Info(name=gfagduis, age=2343)
Info(name=gfagdufasfdfdais, age=2343)
Info(name=gfa4361783ais, age=2343)
Info(name=gfsdfadsfad4361783ais, age=23143)
在使用 @Autowired 注解時,也可以與 @Qualifier(“xxx”) 指定使用哪個方法來獲取對象。
@Bean 注解的屬性解析
value 和 name
name 和 value 兩個屬性是相同的含義的, 在代碼中定義了別名。 為 bean 起一個名字,如果默認沒有寫該屬性,那么就使用方法的名稱為該 bean 的名稱
autowire
裝配方式 有三個選項
- Autowire.NO (默認設(shè)置)
- Autowire.BY_NAME
- Autowire.BY_TYPE
指定 bean 的裝配方式, 根據(jù)名稱 和 根據(jù)類型 裝配, 一般不設(shè)置,采用默認即可。
initMethod
bean 的初始化方法, 直接指定方法名稱即可,不用帶括號。初始方法要在對應(yīng)的POHO中,也就是Info類中。
@Data @AllArgsConstructor @NoArgsConstructor public class Info { ? ? String name; ? ? int age; ? ? private void init(){ ? ? ? ? System.out.println("進入方法2"); ? ? ? ? name = "fhasjdf"; ? ? ? ? age = 12; ? ? } } @Configuration public class BeanInit { ? ? /** ? ? ?* 測試@Bean的作用 ? ? ?*/ ? ? @Bean(name = "info", initMethod = "init") ? ? public Info getInfo(){ ? ? ? ? System.out.println("進入方法"); ? ? ? ? Info info = new Info("gfagduis", 2343); ? ? ? ? System.out.println("結(jié)束方法"); ? ? ? ? return info; ? ? }
最終結(jié)果、:
進入方法
結(jié)束方法
進入方法2
2019-09-24 14:57:11.917 INFO 11656 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-24 14:57:12.048 INFO 11656 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-09-24 14:57:12.051 INFO 11656 --- [ main] z.t.s.u.start.UsulTestStartApplication : Started UsulTestStartApplication in 1.74 seconds (JVM running for 2.246)
>>>>>>>>>>>>>>>服務(wù)啟動執(zhí)行,執(zhí)行加載數(shù)據(jù)等操作<<<<<<<<<<<<<
Info(name=fhasjdf, age=12)
所以最終調(diào)用的是init()方法來創(chuàng)建類。
destroyMethod
bean 的銷毀方法, 在調(diào)用 IoC 容器的 close() 方法時,會執(zhí)行到該屬性指定的方法。不過,只是單實例的 bean 才會調(diào)用該方法,如果是多實例的情況下,不會調(diào)用該方法。
注意:
由于spring構(gòu)造的對象都是單例的,所以只要是從spring ioc中獲取的對象都是同一個,他們中的屬性,即便是私有的非靜態(tài)屬性。都是公用的。
public class MyDisposableBean implements DisposableBean { ? ? public Map<String, String> map = new HashMap<>(); ? ? int i = 0; ? ? private void init(){ ? ? ? ? System.out.println("MyDisposableBean自定義初始化方法"); ? ? } ? ? private void destroyMethod(){ ? ? ? ? System.out.println("自定義銷毀方法,MyDisposableBean對象銷毀"); ? ? } ? ? public void pringt(){ ? ? ? ? System.out.println("-------------------------------"); ? ? ? ? System.out.println("i=" + i); ? ? ? ? System.out.println("map.size=" + map.size()); ? ? ? ? map.entrySet().stream().forEach(item -> System.out.println("map -> ? "+ item.getKey() + "---" + item.getValue())); ? ? } }
@Configuration public class BeanConfigurer { @Bean(name = "MyDisposableBean", initMethod = "init", destroyMethod = "destroyMethod") public MyDisposableBean getMyDisposableBean(){ System.out.println("MyDisposableBean構(gòu)造方法"); return new MyDisposableBean(); } }
@Component public class DisposableBeanTest implements CommandLineRunner { @Override public void run(String... args) throws Exception { MyDisposableBean myDisposableBean = new MyDisposableBean(); MyDisposableBean myDisposableBean1 = new MyDisposableBean(); MyDisposableBean myDisposableBean2 = SpringContextUtils.getBean(MyDisposableBean.class); myDisposableBean2.pringt(); myDisposableBean2.map.put("1", "2"); myDisposableBean2.i = 2; MyDisposableBean myDisposableBean3 = SpringContextUtils.getBean(MyDisposableBean.class); myDisposableBean3.pringt(); myDisposableBean1.pringt(); } }
測試結(jié)果:
MyDisposableBean構(gòu)造方法
MyDisposableBean自定義初始化方法
-------------------------------
i=0
map.size=0
-------------------------------
i=0
map.size=0
-------------------------------
i=2
map.size=1
map -> 1---2
-------------------------------
i=0
map.size=0
可以看出,如果是我們自己在程序中new的對象(myDisposableBean 和 myDisposableBean1),其私有屬性map和i是不變的。不相互影響。
另外兩從spring ioc中獲取的對象(myDisposableBean2 和 myDisposableBean3 )的map和i兩個屬性,是公用的。其中一個對象修改值,name另外一個對象的屬性也相應(yīng)的變化
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis中自定義TypeHandler處理枚舉的示例代碼
typeHandler,是 MyBatis 中的一個接口,用于處理數(shù)據(jù)庫中的特定數(shù)據(jù)類型,下面簡單介紹創(chuàng)建自定義 typeHandler 來處理枚舉類型的示例,感興趣的朋友跟隨小編一起看看吧2024-01-01springboot統(tǒng)一異常處理(返回json)并格式化異常
這篇文章主要介紹了springboot統(tǒng)一異常處理(返回json)并格式化異常,對spring boot的默認異常處理方式進行修改,要統(tǒng)一返回數(shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開發(fā)應(yīng)用,需要的朋友可以參考下2023-07-07SpringBoot整合Shiro框架,實現(xiàn)用戶權(quán)限管理
Apache Shiro是一個強大且易用的Java安全框架,執(zhí)行身份驗證、授權(quán)、密碼和會話管理。作為一款安全框架Shiro的設(shè)計相當巧妙。Shiro的應(yīng)用不依賴任何容器,它不僅可以在JavaEE下使用,還可以應(yīng)用在JavaSE環(huán)境中。2021-06-06Java基于外觀模式實現(xiàn)美食天下食譜功能實例詳解
這篇文章主要介紹了Java基于外觀模式實現(xiàn)美食天下食譜功能,較為詳細的講述了外觀模式的概念、原理并結(jié)合實例形似詳細分析了Java基于外觀模式實現(xiàn)美食天下食譜功能的具體操作步驟與相關(guān)注意事項,需要的朋友可以參考下2018-05-05