介紹了Spring的高級註解,包括@Configuration註解替代XML配置文件、@Bean註解創建和註入Bean、@ComponentScan註解進行註解掃描,配置Bean的底層實現原理等 ...
學習視頻:【孫哥說Spring5:從設計模式到基本應用到應用級底層分析,一次深入淺出的Spring全探索。學不會Spring?只因你未遇見孫哥】
第三章、Spring的高級註解(Spring3.x及以上)
1.配置Bean
Spring在3.x提供的新的註解,用於替換XML配置文件。
@Configuration
public classAppConfig{
}
問題:
- 配置Bean在應用的過程中替換了XML具體的什麼內容?
-
AnnotationConfigApplicationContext
1.創建工廠代碼 ApplicationContext ctx = new AnnotationConfigApplicationContext(); 2.指定配置文件 1. 指定配置bean的Class ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); 2. 指定配置bean所在的路徑 ApplicationContext ctx = new AnnotationConfigApplicationContext("com.baizhi");
- 配置Bean開發的細節分析
-
基於註解開發使用日誌
不能集成Log4j(落後了)
集成新的日誌技術:logback
-
引入相關jar
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.26</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.5.6</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>org.logback-extensions</groupId> <artifactId>logback-ext-spring</artifactId> <version>0.1.5</version> </dependency>
-
引入logback配置文件(logback.xml)
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <!-- 控制台輸出--> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!--格式化輸出:%d標識日期,%thread表示線程名,%-5level:級別從左顯示5個字元寬度 %msg:日誌消息,%n是換行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT"/> </root> </configuration>
-
-
@Configuration註解的本質
本質:也是@Component註解的衍生註解
可以應用<context:component-scan進行掃描,但是實際開發不會這麼做。
-
- 配置Bean開發的細節分析
2.@Bean註解
@Bean註解在配置bean中進行使用,等同於XML配置文件中的<bean標簽
1.@Bean註解的基本使用
- 對象的創建
1. 簡單對象
直接能夠通關new方式創建的對象:User UserService UserDAO
2. 複雜對象
不能通過new方式創建的對象:Connection SqlSessionFactory
```java
/**
* 創建複雜對象
* Connection 不能直接通過new 創建
*/
@Bean
public Connection conn() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?useSSL=false", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
```
- @Bean註解創建複雜對象的註意事項
```java
遺留系統整合比較常見,自己寫還是通過上面的方式
@Bean
public Connection conn1(){
Connection conn = null;
try {
ConnectionFactoryBean factoryBean = new ConnectionFactoryBean();
conn = factoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
```
-
自定義id值
@Bean("id)
-
控制對象創建次數
@Bean @Scope("singleton | prototype") 預設值 singleton
2.@Bean註解的註入
-
用戶自定義類型
@Bean public UserDao userDAO(){ return new UserDaoImpl(); } //可以通過形參傳入userDao,也可以調用方法獲取userDao @Bean public UserService userService(){ UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(userDAO()); return userService; }
-
JDK類型的註入
@Bean public Customer customer(){ Customer customer = new Customer(); customer.setId(1); customer.setName("xiaohei"); return customer; }
-
JDK類型註入的細節分析
如果直接在代碼中進行set方法的調用,會存在耦合的問題
@Configuration @PropertySource("classpath:/init.properties") public class AppConfig1 { @Value("${id}") private Integer id; @Value("${name}") private String name; @Bean public Customer customer(){ Customer customer = new Customer(); customer.setId(id); customer.setName(name); return customer; } }
-
3.@ComponentScan註解
@ComponentScan註解在配置bean中進行使用,等同於xml配置中的context:component-scan標簽
目的:進行相關註解的掃描 @Component @Value…
1.基本使用
@Configuration
@ComponentScan(basePackages = "com.baizhi.scan")
public class AppConfig2 {
}
等價於: <context:component-scan base-package=""/>
2.排除、包含的使用
-
排除
@Configuration @ComponentScan(basePackages = "com.baizhi.scan", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class}) ,@ComponentScan.Filter(type = FilterType.ASPECTJ,pattern = "*..User1")}) // 第一個排除Service註解,排除了user2對象,第二個排除了User1類 public class AppConfig2 { } 註意**:針對ASPECTJ和REGEX後面的值是pattern,其他都是value**
-
包含
@ComponentScan(basePackages = "com.baizhi.scan", useDefaultFilters = false,//放棄預設掃描策略,必須指定為false includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})}) public class AppConfig2 { }
4.Spring工廠創建對象的多種配置方式
1.多種配置方式的應用場景 @Component @Bean @Import
2.配置優先順序
@Component及其衍生註解 < @Bean < 配置文件bean標簽
優先順序高的配置 覆蓋優先順序低的配置(如果對@Component註解的類不滿意,可以用@Bean註解的類進行覆蓋,但是id必須同名)
@ImportResource("applicationContext.xml")// 與spring配置文件集成,先讀取配置@Bean 在讀取配置文件
- 解決基於註解進行配置的耦合問題
@Configuration
@ImportResource("applicationContext.xml")
public class AppConfig4 {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
}
**在applicationContext.xml 配置bean解耦合**
<bean id="userDAO" class="com.baizhi.injection.UserServiceImplNew"/>
-
這樣產生的問題,還是會有耦合,因為要在原有的AppConfig配置類添加集成代碼,解決方法:
// 新建立一個AppConfig5的配置類,將集成代碼放到此類中,再讀取多個配置類,可以根據包地址讀取所有的配置類 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class,AppConfig5.class); ApplicationContext ctx1 = new AnnotationConfigApplicationContext("com.baizhi"); UserDao userDao = (UserDao) ctx.getBean("userDAO"); userDao.save();
5.整合多個配置信息
-
為什麼會有多個配置信息
根絕不同類型(事務、資料庫連接)拆分多個配置bean的開發,是一種模塊化開發的形式,也體現了面向對象各司其職的設計思想
-
多配置信息整合的方式
- 多個配置bean的整合
- 配置Bean與@Component相關註解的整合
- 配置Bean與SpringXML配置文件的整合
-
整合多種配置
- 如何使多配置的信息 彙總成一個整體
- 實現跨配置的註入
1.多個配置Bean的整合
- 多配置信息彙總
- base-package進行多個配置Bean的整合
2. @Import
1. 可以創建對象
2. 多配置bean的整合
3. 在工廠創建時,指定多個配置Bean的Class對象
```java
// 這種方式日常開發使用較少,瞭解即可
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class,AppConfig5.class);
```
- 跨配置進行註入
**在應用配置Bean的過程中,不管使用哪種方式進行配置信息的彙總,其操作方式都是通過在成員變數添加@Autowired註解完成**
@Configuration
@Import(AppConfig2.class)
public class AppConfig1 {
@Autowired
private UserDao userDAO;
@Bean
public UserService userService() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDAO);
return userService;
}
}
@Configuration
public class AppConfig2 {
@Bean
public UserDao userDAO(){
return new UserDaoImpl();
}
}
適用於應用配置Bean的所有場景
2.配置Bean與@Component相關註解的整合
@Component(@Repostitory)
public class UserDAOImpl implements UserDAO{
}
@Configuration
@ComponentScan("")
public lcass AppConfig3{
@Autowired
private UserDao userDao;
@Bean
public UserService userService() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
return userService;
}
}
3.配置Bean與配置文件整合
1.遺留系統的整合
2.配置覆蓋
<bean id="userDAO" class="com.baizhi.injection.UserDaoImpl"/>
@Configuration
@ImportResource("applicationContext.xml")
public class AppConfig4 {
@Autowired
private UserDao userDao;
@Bean
public UserService userService() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
return userService;
}
}
6.配置Bean底層實現原理
Spring在配置Bean加入了@Configuration註解後,底層久會通過Cglib的代理方式,來進行對象相關的配置、處理
作者:揚眉劍出鞘
出處: https://www.cnblogs.com/eyewink/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。