<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          詳細(xì)講解 Spring 中的 @Bean 注解

          共 8195字,需瀏覽 17分鐘

           ·

          2021-08-05 09:03

          隨著SpringBoot的流行,我們現(xiàn)在更多采用基于注解式的配置從而替換掉了基于XML的配置,所以本篇文章我們主要探討基于注解的@Bean以及和其他注解的使用;

          @Bean 基礎(chǔ)概念

          • @Bean:Spring的@Bean注解用于告訴方法,產(chǎn)生一個(gè)Bean對(duì)象,然后這個(gè)Bean對(duì)象交給Spring管理。產(chǎn)生這個(gè)Bean對(duì)象的方法Spring只會(huì)調(diào)用一次,隨后這個(gè)Spring將會(huì)將這個(gè)Bean對(duì)象放在自己的IOC容器中;

          • SpringIOC 容器管理一個(gè)或者多個(gè)bean,這些bean都需要在@Configuration注解下進(jìn)行創(chuàng)建,在一個(gè)方法上使用@Bean注解就表明這個(gè)方法需要交給Spring進(jìn)行管理;

          • @Bean是一個(gè)方法級(jí)別上的注解,主要用在@Configuration注解的類(lèi)里,也可以用在@Component注解的類(lèi)里。添加的bean的id為方法名;

          • 使用Bean時(shí),即是把已經(jīng)在xml文件中配置好的Bean拿來(lái)用,完成屬性、方法的組裝;比如@Autowired , @Resource,可以通過(guò)byTYPE(@Autowired)、byNAME(@Resource)的方式獲取Bean;

          • 注冊(cè)Bean時(shí),@Component , @Repository , @ Controller , @Service , @Configration這些注解都是把你要實(shí)例化的對(duì)象轉(zhuǎn)化成一個(gè)Bean,放在IoC容器中,等你要用的時(shí)候,它會(huì)和上面的@Autowired , @Resource配合到一起,把對(duì)象、屬性、方法完美組裝;

          • @Configuration與@Bean結(jié)合使用:@Configuration可理解為用spring的時(shí)候xml里面的標(biāo)簽,@Bean可理解為用spring的時(shí)候xml里面的標(biāo)簽;

          快速搭建一個(gè)maven項(xiàng)目并配置好所需要的Spring 依賴(lài)

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.13.RELEASE</version>
          </dependency>

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.13.RELEASE</version>
          </dependency>

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.13.RELEASE</version>
          </dependency>

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.13.RELEASE</version>
          </dependency>

          在src根目錄下創(chuàng)建一個(gè)AppConfig的配置類(lèi),這個(gè)配置類(lèi)也就是管理一個(gè)或多個(gè)bean 的配置類(lèi),并在其內(nèi)部聲明一個(gè)myBean的bean,并創(chuàng)建其對(duì)應(yīng)的實(shí)體類(lèi)

          @Configuration
          public class AppConfig {

              // 使用@Bean 注解表明myBean需要交給Spring進(jìn)行管理
              // 未指定bean 的名稱(chēng),默認(rèn)采用的是 "方法名" + "首字母小寫(xiě)"的配置方式
              @Bean
              public MyBean myBean(){
                  return new MyBean();
              }
          }

          public class MyBean {

              public MyBean(){
                  System.out.println("MyBean Initializing");
              }
          }

          然后再創(chuàng)建一個(gè)測(cè)試類(lèi)SpringBeanApplicationTests,測(cè)試上述代碼的正確性

          public class SpringBeanApplicationTests {

              public static void main(String[] args) {
                  ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
                  context.getBean("myBean");
              }
          }

          輸出 : MyBean Initializing

          深入了解@Bean注解的源代碼

          @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public @interface Bean {
              @AliasFor("name")
              String[] value() default {};
              @AliasFor("value")
              String[] name() default {};
              Autowire autowire() default Autowire.NO;
              String initMethod() default "";
              String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
          }
          @Bean的屬性:
          • value:bean別名和name是相互依賴(lài)關(guān)聯(lián)的,value,name如果都使用的話(huà)值必須要一致;

          • name:bean名稱(chēng),如果不寫(xiě)會(huì)默認(rèn)為注解的方法名稱(chēng);

          • autowire:自定裝配默認(rèn)是不開(kāi)啟的,建議盡量不要開(kāi)啟,因?yàn)樽詣?dòng)裝配不能裝配基本數(shù)據(jù)類(lèi)型、字符串、數(shù)組等,這是自動(dòng)裝配設(shè)計(jì)的局限性,并且自動(dòng)裝配不如依賴(lài)注入精確;

          • initMethod:bean的初始化之前的執(zhí)行方法,該參數(shù)一般不怎么用,因?yàn)橥耆梢栽诖a中實(shí)現(xiàn);

          • destroyMethod:默認(rèn)使用javaConfig配置的bean,如果存在close或者shutdown方法,則在bean銷(xiāo)毀時(shí)會(huì)自動(dòng)執(zhí)行該方法,如果你不想執(zhí)行該方法,則添加@Bean(destroyMethod="")來(lái)防止出發(fā)銷(xiāo)毀方法;

          如果發(fā)現(xiàn)銷(xiāo)毀方法沒(méi)有執(zhí)行,原因是bean銷(xiāo)魂之前程序已經(jīng)結(jié)束了,可以手動(dòng)close下如下:

          AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
          User bean2 = applicationContext2.getBean(User.class);
          System.out.println(bean2);
          //手動(dòng)執(zhí)行close方法
          applicationContext2.close();

          運(yùn)行結(jié)果如下:

          初始化用戶(hù)bean之前執(zhí)行
          User [userName=張三, age=26]
          bean銷(xiāo)毀之后執(zhí)行

          我們發(fā)現(xiàn)@baen注解的@Target是ElementType.METHOD,ElementType.ANNOTATION_TYPE也就說(shuō)@Bean注解可以在使用在方法上,以及一個(gè)注釋類(lèi)型聲明

          @Bean 注解與其他注解一起使用

          @Bean注解不止這幾個(gè)屬性,它還能和其他的注解一起配合使用,請(qǐng)繼續(xù)往下看:

          @Profile 注解

          @Profile的作用是把一些meta-data進(jìn)行分類(lèi),分成Active和InActive這兩種狀態(tài),然后你可以選擇在active 和在Inactive這兩種狀態(tài)下配置bean,在Inactive狀態(tài)通常的注解有一個(gè)!操作符,通常寫(xiě)為:@Profile("!p"),這里的p是Profile的名字。

          三種設(shè)置方式:

          • 可以通過(guò)ConfigurableEnvironment.setActiveProfiles()以編程的方式激活。
          • 可以通過(guò)AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME (spring.profiles.active )屬性設(shè)置為JVM屬性。
          • 作為環(huán)境變量,或作為web.xml 應(yīng)用程序的Servlet 上下文參數(shù)。也可以通過(guò)@ActiveProfiles注解在集成測(cè)試中以聲明方式激活配置文件。

          作用域:

          • 作為類(lèi)級(jí)別的注解在任意類(lèi)或者直接與@Component 進(jìn)行關(guān)聯(lián),包括@Configuration 類(lèi)
          • 作為原注解,可以自定義注解
          • 作為方法的注解作用在任何方法

          注意:

          如果一個(gè)配置類(lèi)使用了Profile 標(biāo)簽或者@Profile 作用在任何類(lèi)中都必須進(jìn)行啟用才會(huì)生效,如果@Profile({“p1”,"!p2"})標(biāo)識(shí)兩個(gè)屬性,那么p1 是啟用狀態(tài) 而p2 是非啟用狀態(tài)的。

          例如:

          @Profile("dev")
          public @Bean("activityMongoFactory")
          MongoDbFactory activityMongoFactoryDev(MongoClient activityMongo) {
              return new SimpleMongoDbFactory(activityMongo, stringValueResolver.resolveStringValue("${mongodb.dev.database}"));
          }

          @Scope 注解

          在Spring中對(duì)于bean的默認(rèn)處理都是單例的,我們通過(guò)上下文容器.getBean方法拿到bean容器,并對(duì)其進(jìn)行實(shí)例化,這個(gè)實(shí)例化的過(guò)程其實(shí)只進(jìn)行一次,即多次getBean 獲取的對(duì)象都是同一個(gè)對(duì)象,也就相當(dāng)于這個(gè)bean的實(shí)例在IOC容器中是public的,對(duì)于所有的bean請(qǐng)求來(lái)講都可以共享此bean。

          如果我們不想把這個(gè)bean被所有的請(qǐng)求共享或者說(shuō)每次調(diào)用我都想讓它生成一個(gè)新的bean實(shí)例,該怎么實(shí)現(xiàn)呢?

          bean的多個(gè)實(shí)例

          bean的非單例原型范圍會(huì)使每次發(fā)出對(duì)該特定bean的請(qǐng)求時(shí)都創(chuàng)建新的bean實(shí)例,也就是說(shuō),bean被注入另一個(gè)bean,或者通過(guò)對(duì)容器的getBean()方法調(diào)用來(lái)請(qǐng)求它。

          下面,我們通過(guò)一個(gè)示例來(lái)說(shuō)明bean的多個(gè)實(shí)例

          新建一個(gè)ConfigScope配置類(lèi),用來(lái)定義多例的bean

          @Configuration
          public class ConfigScope {

              /**
               * 為myBean起兩個(gè)名字,b1 和 b2
               * @Scope 默認(rèn)為 singleton,但是可以指定其作用域
               * prototype 是多例的,即每一次調(diào)用都會(huì)生成一個(gè)新的實(shí)例。
               */

              @Bean({"b1","b2"})
              @Scope("prototype")
              public MyBean myBean(){
                  return new MyBean();
              }
          }

          注意:prototype代表bean對(duì)象的定義為任意數(shù)量的對(duì)象實(shí)例,所以指定為prototype屬性可以定義為多例,也會(huì)每一次調(diào)用都會(huì)生成一個(gè)新的實(shí)例。

          singleton和prototype 一般都用在普通的Java項(xiàng)目中,而request、session、application、websocket都用于web應(yīng)用中。

          @Lazy 注解

          表明一個(gè)bean 是否延遲加載,可以作用在方法上,表示這個(gè)方法被延遲加載;可以作用在@Component (或者由@Component 作為原注解) 注釋的類(lèi)上,表明這個(gè)類(lèi)中所有的bean 都被延遲加載。

          如果沒(méi)有@Lazy注釋?zhuān)蛘這Lazy 被設(shè)置為false,那么該bean 就會(huì)急切渴望被加載;除了上面兩種作用域,@Lazy 還可以作用在@Autowired和@Inject注釋的屬性上,在這種情況下,它將為該字段創(chuàng)建一個(gè)惰性代理,作為使用ObjectFactory或Provider的默認(rèn)方法。

          下面來(lái)演示一下:

          @Lazy
          @Configuration
          @ComponentScan(basePackages = "com.spring.configuration.pojo")
          public class AppConfigWithLazy {

              @Bean
              public MyBean myBean(){
                  System.out.println("myBean Initialized");
                  return new MyBean();
              }

              @Bean
              public MyBean IfLazyInit(){
                  System.out.println("initialized");
                  return new MyBean();
              }
          }

          @Primary 注解

          指示當(dāng)多個(gè)候選者有資格自動(dòng)裝配依賴(lài)項(xiàng)時(shí),應(yīng)優(yōu)先考慮bean。此注解在語(yǔ)義上就等同于在Spring XML中定義的bean 元素的primary屬性。

          注意:除非使用component-scanning進(jìn)行組件掃描,否則在類(lèi)級(jí)別上使用@Primary不會(huì)有作用。如果@Primary 注解定義在XML中,那么@Primary 的注解元注解就會(huì)忽略,相反的話(huà)就可以?xún)?yōu)先使用。

          @Primary 的兩種使用方式:

          • 與@Bean 一起使用,定義在方法上,方法級(jí)別的注解
          • 與@Component 一起使用,定義在類(lèi)上,類(lèi)級(jí)別的注解

          新建一個(gè)AppConfigWithPrimary類(lèi),在方法級(jí)別上定義@Primary注解

          @Configuration
          public class AppConfigWithPrimary {

              @Bean
              public MyBean myBeanOne(){
                  return new MyBean();
              }

              @Bean
              @Primary
              public MyBean myBeanTwo(){
                  return new MyBean();
              }
          }

          上面代碼定義了兩個(gè)bean ,其中myBeanTwo 由@Primary 進(jìn)行標(biāo)注,表示它首先會(huì)進(jìn)行注冊(cè),使用測(cè)試類(lèi)進(jìn)行測(cè)試。

          來(lái)源:blog.csdn.net/weixin_42140261/article/details/104864333


          END


          順便給大家推薦一個(gè)GitHub項(xiàng)目,這個(gè) GitHub 整理了上千本常用技術(shù)PDF,絕大部分核心的技術(shù)書(shū)籍都可以在這里找到,

          GitHub地址:https://github.com/javadevbooks/books

          Gitee地址:https://gitee.com/javadevbooks/books

          電子書(shū)已經(jīng)更新好了,你們需要的可以自行下載了,記得點(diǎn)一個(gè)star,持續(xù)更新中..



          瀏覽 35
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91爱爱视频 | 日韩免费高清在线视频 | 黑人巨大两根挤进一个 | 欧美久久大香蕉 | 大肉大捧一进一出两腿 |