大廠面試官最常問的@Configuration+@Bean(JDKConfig編程方式)

大廠面試官最常問的@Configuration+@Bean(JDKConfig編程方式)案例分享
大廠面試官最常問的@Configuration+@Bean(JDKConfig編程方式)

現在大部分的Spring項目都採用了基於註解的配置,採用了@Configuration 替換標籤的做法。一行 簡單的註解就可以解決很多事情。但是,其實每一個註解背後都有很多值得學習和思考的內容。這 些思考的點也是很多大廠面試官喜歡問的內容。

@Configuration處理類:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition

@Bean處理類:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition

· 項目包結構

F:.

├─java

│ └─com

│ └─example

│ └─demo4

│ │ Demo4Application.java

│ │

│ ├─configuration

│ │ PersonConfiguration.java

│ │ StuConfiguration.java

│ │

│ ├─controll

│ │ StuController.java

│ │

│ ├─dao

│ │ StuDao.java

│ │ StuDaoImp.java

│ │

│ ├─entity

│ │ Person.java

│ │ Stu.java

│ │

│ └─server

│ StuService.java

│ StuServiceImp.java

└─resources

application.properties

project.text

· Beans依賴圖

·

·

問題1:@Configuration和@Component區別(@Configuration自動cglib動態代理)

·

o @Configuration 中所有帶 @Bean 註解的方法都會被動態代理,因此調用該方法返回的都是同一個實例(Spring啓動時會專門處理@Configuration)。proxyBeanMethods可以設置成false,取消代理。除此之外以下@Bean無法動態代理。

o 配置類必須以類的形式提供(不能是工廠方法返回的實例),允許通過生成子類在運行時增強(cglib 動態代理)。

o 配置類不能是 final 類

o 配置類必須是非本地的(即不能在方法中聲明,不能是 private)。

o 任何嵌套配置類都必須聲明爲static。

o @Bean必須是單例(默認就是,別改成prototype)

o @Component裏面的@Bean不是代理的

o 代理和不代理的區別如下代碼:

//拿到@Bean->person

Person person = context.getBean(Person.class);

//拿到組件

PersonConfiguration personConfiguration = context.getBean(PersonConfiguration.class);

//執行組件裏面的person()方法

Person person1=personConfiguration.person();

//使用stu

System.out.println(stu.getClass().getName());

//獲取組件裏面的person()方法對象的hashCode

System.out.println("person1:"+person1.getClass().getName() + "@" + Integer.toHexString(person1.hashCode()));

//@Bean->person對象的hashCode

System.out.println("person:"+person.getClass().getName() + "@" + Integer.toHexString(person.hashCode()));

//從IOC容器中取出存在的personBean

Map<String, Person> beansOfType = context.getBeansOfType(Person.class);

//對比知道不代理執行組件裏面的person()方法的對象不會被Spring管理,代理就會管理

System.out.println("beansOfType:"+beansOfType.get("person").getClass().getName() + "@" + Integer.toHexString(person.hashCode()));

·

問題2:expected single matching bean but found 2

·

o

同類型多個Beans,引發原因比如使用了context.getBean(Stu.class)、@Autowired只用ByType類獲取或者注入Beans的時候

o

o

使用名稱獲取,不優先使用ByType,==如果是其它第三方(也許第三方直接ByType)那麼可以採取【禁止使用】或【優先使用】

o

o

禁止使用

o

o @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })

o application.properties裏配置:spring.autoconfigure.exclude=全類名,全類名

o

優先使用(在設計層面不建議這樣使用)

o

o

@Bean

@Primary

public Person person() {

return new Person();

}

o

o

==正確姿態約定好命名規則尤爲重要==

o

·

問題3:could not be registered. A bean with that name has already been defined in file

·

o 組件重複問題,大多使用配置:spring.main.allow-bean-definition-overriding=true

o 以上配置會覆蓋Bean,並且依然產生具體對象

具體底層實現類(誰定義存儲了這些註冊類??):

·

AnnotatedGenericBeanDefinition:存儲@Configuration註解註釋的類

·

·

ScannedGenericBeanDefinition:存儲@Component、@Service、@Controller等註解註釋的類

·

·

spring初始化時,會用GenericBeanDefinition或是ConfigurationClassBeanDefinition(用@Bean註解註釋的類)存儲用戶自定義的Bean,在初始化Bean時,又會將其轉換爲RootBeanDefinition

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章