說說你對@Configuration的理解?
定義
@Configuration這個注解是一個類注解,加在類上,標識該類是一個配置類,讓這個類的功能等同于一個bean xml組態檔,
@Configuration
public class SpringConfig {
}
上面代碼類似于下面的xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
</beans>
一般 @Configuration 都是和 @Bean 注解結合使用的,上文代碼塊中使用 @Configuration 定義了一個配置類,相當于定義了一個空的 xml 組態檔,此時我們要在SpringBean 類中注冊bean,那么我們就要用到@Bean注解了,
@Bean
這個注解是一個方法注解,用在方法上,表示通過方法來定義一個bean,默認將方法名稱作為bean名稱,將方法回傳值作為bean物件,注冊到spring容器中,類似于bean xml組態檔中的bean元素,用來在spring容器中注冊一個bean,
@Confuguration
public class SpringConfig {
// 匯入自定義的bean:bean名稱為方法默認值:user1
@Bean
public User user1() {
return new User();
}
// bean名稱通過value指定:user2Bean
@Bean("user2Bean")
public User user2() {
return new User();
}
// 匯入第三方bean
@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("123");
return ds;
}
}
用法
@Configuration注解的使用步驟:
- 定義一個類,在類上添加
@Configuration注解; - 通過
AnnotationConfigApplicationContext容器來加載@Configuration注解修飾的配置類,會將配置類中所有的bean注冊到spring容器中,
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
拓展
如果去掉 @Configuration,會怎樣?
舉個例子:
定義一個User類和Order類
public class User {
public User() {
System.out.println("無參創建User");
}
}
public class Order {
private User user;
public Order(User user) {
this.user = user;
}
@Override
public String toString() {
return "Order{" +
"user=" + user +
'}';
}
}
定義一個配置類
//@Configuration
public class SpringConfig {
// bean名稱為方法默認值:user1
@Bean
public User user() {
return new User();
}
@Bean
public Order order() {
System.out.println("呼叫order()方法");
return new Order(this.user());
}
@Bean()
public Order order2() {
System.out.println("呼叫order2()方法");
return new Order(this.user());
}
}
測驗類
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
for (String beanName : ctx.getBeanDefinitionNames()) {
System.out.printf("beanName: %s \t bean物件: %s\n", beanName, ctx.getBean(beanName));
}
}
}
① 加上 @Configuration 注解時輸出的結果:
無參創建User
呼叫order()方法
呼叫order2()方法
(這里省略Spring容器創建時默認加載的bean)
beanName: springConfig bean物件: cn.afei.config.SpringConfig$$EnhancerBySpringCGLIB$$f76b28e8@4ae3c1cd
beanName: user bean物件: cn.afei.domain.User@29f69090
beanName: order bean物件: Order{user=cn.afei.domain.User@29f69090}
beanName: order2 bean物件: Order{user=cn.afei.domain.User@29f69090}
加上 @Configuration,類中定義了3個Bean,Order中注入User物件時,會復用創建好的User物件,User的構造器只被呼叫了一次,保證了User物件單例,
被@Configuration修飾的bean最后輸出的時候帶有
EnhancerBySpringCGLIB的字樣,說明這個bean是被CGLIB處理過的,變成了一個代理物件,
② 去掉 @Configuration 注解時輸出的結果:
無參創建User
呼叫order()方法
無參創建User
呼叫order2()方法
無參創建User
beanName: springConfig bean物件: cn.afei.config.SpringConfig@543c6f6d
beanName: user bean物件: cn.afei.domain.User@13eb8acf
beanName: order bean物件: Order{user=cn.afei.domain.User@51c8530f}
beanName: order2 bean物件: Order{user=cn.afei.domain.User@7403c468}
去掉了 @Configuration,類中定義了3個Bean,每個Bean都會去創建一個User物件,User的構造器被呼叫了三次,
沒有@Configuration注解的bean沒有Cglib的字樣,
被@Configuration修飾的類,spring容器中會通過cglib給這個類創建一個代理,代理會攔截所有被@Bean修飾的方法,默認情況(bean為單例)下確保這些方法只被呼叫一次,從而確保這些bean是同一個bean,即單例的,
總結
- @Configuration注解修飾的類,會被spring通過cglib做增強處理,通過cglib會生成一個代理物件,代理會攔截所有被@Bean注解修飾的方法,可以確保這些bean是單例的,
- 不管@Bean所在的類上是否有@Configuration注解,@Bean注解都會生效,都可以將@Bean修飾的方法作為一個bean注冊到spring容器中,
參考
https://www.bilibili.com/video/BV1Fi4y1S7ix/
http://itsoku.com/course/5/99
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/512970.html
標籤:Java
上一篇:Docker 部署 Kibana
下一篇:詳解MongoDB索引優化
