Spring配置進階
Spring 容器提供配置元數據有三種方式
- XML配置文件。
- 基于注解的配置。
- 基于java的配置。
一、自動裝配
應用程序上下文為你找出依賴項的過程,Spring會在上下文中自動查找,并自動給bean裝配與其關聯的屬性
Spring中實現自動裝配的方式有兩種:
- XML文件
- 注解
(1)通過xml文件實現自動裝配
1、通過xml文件實現自動裝配
xml配置文件中的
<bean>
要配置autowire
屬性
autowire屬性值:
模式 | 描述 |
---|---|
no | 這是默認的設置,它意味著沒有自動裝配,你應該使用顯式的bean引用來連線。你不用為了連線做特殊的事。, |
byName | 由屬性名自動裝配。Spring 容器看到在 XML 配置文件中 bean 的自動裝配的屬性設置為 byName。然后嘗試匹配,并且將它的屬性與在配置文件中被定義為相同名稱的 beans 的屬性進行連接。 |
byType | 由屬性數據類型自動裝配。Spring 容器看到在 XML 配置文件中 bean 的自動裝配的屬性設置為 byType。然后如果它的類型匹配配置文件中的一個確切的 bean 名稱,它將嘗試匹配和連接屬性的類型。如果存在不止一個這樣的 bean,則一個致命的異常將會被拋出 |
constructor | 類似于 byType,但該類型適用于構造函數參數類型。如果在容器中沒有一個構造函數參數類型的 bean,則一個致命錯誤將會發生。 |
1)byName屬性值
Spring會根據class屬性找到實體類,然后查詢實體類中所有setter方法的名字,根據setter方法后面的名字,再到配置文件中尋找一個與該名字相同id的Bean,注入進來
autowire屬性賦值>>class找到對應類>>查詢對應setter方法>>對應id的Bean對象
<bean id="iDeptDao" class="org.example.dao.impl.DeptImpl" autowire="byName"/>
2)byType屬性值
Spring會自動尋找一個與該屬性類型相同的Bean,注入進來
<bean id="iDeptService" class="org.example.service.impl.DeptServiceImpl autowire="byType">
(2)通過注解實現自動裝配
二、Spring注解分類
1、使用注解前的準備:
//spring-config.xml文件配置數據
<!-- 加入掃描包,配置根路徑,查找根路徑下使用的注解--> <context:component-scan base-package="org.example"/>
以注解為主,XML為輔。
@Component(組件),@Service(服務),@Controller(控制器),@Repository(*/r??pɑ?z?t??ri/*數據倉庫)
1、Spring類注解
@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named注解,都是添加在類上面的類級別注解
Spring容器根據注解的過濾規則掃描讀取注解Bean定義類,并將其注冊到Spring IoC容器中。
1、使用asm技術掃描.class文件,并將包含@Component、@Controller、@Service、@Repository或者其他自定義的的bean注冊到beanFactory中,
- @Component : 通配
- @Repository:用于聲明DAO層的
- @Service:用于業務層
- @Controller:用于控制器 (暫時先不用,后面接觸Spring MVC再使用)
2、然后spring在注冊處理器
3、實例化處理器,然后將其放到beanPostFactory中,然后我們就可以在類中進行使用了。
4、創建bean時,會自動調用相應的處理器進行處理。
2、類內部注解
@Autowire、@Value、@Resource注解等,都是添加在類內部的字段或者方法上的類內部注解。
SpringIoC容器通過Bean后置注解處理器解析Bean內部的注解,比如Spring實現@Autowire解析和注入的核心的類是通過AutowiredAnnotationBeanPostProcessor來實現的
//@Component("deptService"),
//@Service類注解Service層
@Service("deptService")
public class DeptServiceImpl implements IDeptService {@Autowired//Autowired類內部注解,可以注解變量或方法private IDeptMapper deptMapper;
}
三、注解實現自動裝配
2.使用注解(類內部注解)
-
@Autowired注解
只按照類型byType匹配, 默認情況匹配的Bean只有一個,匹配不到報錯BeanCreationException 異常
- 可使用在變量和setter方法上, xml文件中注解autowrie刪除
若要匹配多個類型, 引入:
//1.注解在屬性上 @Autowired @Qualifier("類型2") private IDeptMapper deptMapper; //2.注解setter方法上(同一變量的2種二選一)@Autowiredpublic void setiDeptDaoMapper(IDeptMapper iDeptMapper) {this.iDeptMapper = iDeptMapper;}
-
@Qualifier注解(
當ioc容器根據屬性類型去容器中找找到多個相同類型的組件,再將屬性的名稱作為組件(bean)的id去容器中查找找不到時就是用這兩個注解搭配,指定需要裝配的bean的id。
和Autowired搭配使用
-
@Resource注解
- 可以寫在字段和setter方法上(2選1)
默認按名稱進行裝配
@Resource有兩個重要的屬性:name和type,而Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型
-
默認按名字匹配
@Resource private SqlSessionFactory sqlSessionFactory;
-
按類型: 效果和@Autowired一樣
@Resource(type = SqlSessionFactory.class)private SqlSessionFactory sqlSessionFactory;
-
匹配順序
同時name和type一致的bean對象>>指定的name>>指定type>>什么也沒指定name
3.基于注解聲明組件(類注解)
目前常用的組件有:@Component(組件),@Service(服務),@Controller(控制器),@Repository(數據倉庫)
1.@Component注解
通用的注解,可標注任意類為 Spring
組件(一個 Bean 不知道屬于哪個層時使用)
說明:如果一個類中有@Component,沒有指定名稱,那么這個組件名稱就是類名首字母小寫
//@Component //默認空指向deptMapperImpl
@Component("deptMapper")
public class DeptMapperImpl implements IDeptMapper {@Resourceprivate SqlSessionFactory sqlSessionFactory;
}
4.使用完類注解
刪除掉聲明的dao層的bean信息,以及service信息,只保留基礎配置信息
//bean標簽都刪除 <!-- <bean id="iDeptDao" class="org.example.dao.impl.DeptImpltowire="byName"> --> <!-- <bean id="iDeptDao1" class="org.example.dao.impl.IDeptMapperImpl1 -->
四.JavaConfig
JavaConfig是指基于java配置的spring。傳統的Spring一般都是基本xml配置的,后來spring3.0新增了許多JavaConfig的注解
任何一個標注了@Configuration的Java類定義都是一個JavaConfig配置類
package org.example;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;import javax.annotation.Resource;
import javax.sql.DataSource;/*** @author Arran* @version 1.0* @description: 基于java配置的spring* @date 2024/07/06 上午 11:59*/
//在類上打上這一標簽,表示這個類是配置類
//表明該類是一個JavaConfig形式的Spring Ioc容器的配置類@Configuration//被該注解標識的類,
//讀取數據源
@PropertySource("classpath:source.properties")
public class Myconfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;//相當于spring.xml文件的bean對象@Beanpublic DataSource dataSource() {DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName(driver);druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return druidDataSource;}
}
注解 | 說明 |
---|---|
@Configuration | 在類上打上這一標簽,表示這個類是配置類 |
@ComponentScan | 相當于xml的<context:componentscan basepakage=> |
@Bean | bean的定義,相當于xml的<bean id="objectMapper" class="org.it.map.ObjectMapper" /> |
@EnableWebMvc | 相當于xml的<mvc:annotation-driven> ,springMVC階段涉及 |
@ImportResource | 相當于xml的 <import resource="applicationContext-cache.xml"> |
@PropertySource | spring 3.1開始引入,它是基于java config的注解,用于讀取properties文件 |
@Profile | spring3.1開始引入,一般用于多環境配置,激活時可用@ActiveProfiles注解,@ActiveProfiles(“dev”) |
@Value | 讀取外部配置文件對應的property |
xml和java配置的區別
1.表達形式層面(二者區別)
- 基于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-3.0.xsd”> </beans>
-
而基于JavaConfig的配置方式是這樣:
@Configuration
public class MockConfiguration{
//bean定義
}
2.注冊bean定義層面
-
基于XML的配置形式是這樣:
<bean id=“mockService” class=“…MockServiceImpl”>
…
</bean> -
而基于JavaConfig的配置形式是這樣的:
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl();
}
}任何一個標注了@Bean的方法,其返回值將作為一個bean定義注冊到Spring的IoC容器,方法名將默認成該bean定義的id。
@Bean一般用在使用第三方類來生成對象注入到spring容器的情況下使用
3.表達依賴注入關系層面
-
為了表達bean與bean之間的依賴關系,在XML形式中一般是這樣:
<bean id=“dependencyService” class=“DependencyServiceImpl”></bean>
<bean id=“mockService” class=“…MockServiceImpl”>
<propery name =“dependencyService” ref=“dependencyService” />
</bean> -
而基于JavaConfig的配置形式是這樣的:
@Configuration
public class MockConfiguration{
@Bean
public DependencyService dependencyService(){
return new DependencyServiceImpl();
}
如果一個bean的定義依賴其他bean,則直接調用對應的JavaConfig類中依賴bean的創建方法就可以了。
五MapperScannerConfigurer配置
MyBatis中可以使用SqlSession的getMapper(Class type)方法,根據指定的映射器和映射文件直接生成實現類,這樣不必自行編寫映射器的實現類,就可以調用映射器的方法進行功能實現。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property><property name="basePackage" value="mapper路徑"></property>
</bean>
- basePackage屬性中可以包含多個包名,多個包含之間使用逗號或分號隔開。
- MapperScannerConfigurer會為所有又它創建的映射器實現開啟自動裝配,也就是MapperScannerConfigurer創建的所有映射器實現都會被自動注入SqlSessionFactory例,因此在如上示例中配置DAO組件時無需顯示注入SqlSessionFactory實例
- 映射器被注冊到Spring容器時,Spring會根據其接口名稱為其命名,默認規則是首字母小寫的非完全限定類名。例如EmpMapper類型的組件會被默認命名為empMapper