一.Spring的API -ApplicationContext
1.1,ApplicationContext的繼承體系
applicationContext: 接口類型,代表應(yīng)用上下文,可以通過(guò)其 實(shí)例 獲得Spring容器中的bean對(duì)象
1.2,ApplicationContext的實(shí)現(xiàn)類
1)ClassPathXmlApplicationContext
它是從**類的根路徑下(target/classes)**加載配置文件
2)FileSystemXmlApplicationContext
它是從**磁盤路徑上**加載配置文件,配置文件可以在磁盤的任意位置
3)AnnotationConfigApplicationContext
當(dāng)使用注解配置容器對(duì)象時(shí),需要使用此類來(lái)創(chuàng)建spring容器.使用它來(lái)讀取注解.
1.3,getBean()方法使用
public Object getBean(String name) throws BeansException{
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
public <T> T getBean(Class<T> requiredType) throws BeansException{
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
//其中, 當(dāng)參數(shù)的數(shù)據(jù)類型時(shí)字符串時(shí), 表示根據(jù)Bean的id從容器中獲得Bean實(shí)例,返回Object,需要強(qiáng)轉(zhuǎn).
//當(dāng)參數(shù)的數(shù)據(jù)類型時(shí)class類型時(shí), 表示根據(jù)類型從容器中匹配Bean實(shí)例, 當(dāng)容器中相同類型的Bean有多個(gè)時(shí),則此方法會(huì)報(bào)錯(cuò)
getBean()方法使用
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//參數(shù)的數(shù)據(jù)類型時(shí)字符串
UserService userService = (UserService)applicationContext.getBean("userService");
//參數(shù)的數(shù)據(jù)類型時(shí)class類型
UserService userService2 = applicationContext.getBean(UserService.class);
二,Spring配置數(shù)據(jù)源(數(shù)據(jù)庫(kù)連接池)dataSource
2.1 數(shù)據(jù)源(連接池)的作用
減少頻繁的請(qǐng)求連接,釋放資源
數(shù)據(jù)源(連接池)是提高程序性能而出現(xiàn)的, 事先實(shí)例化數(shù)據(jù)源, 初始化部分連接資源.使用連接資源時(shí)從數(shù)據(jù)源中獲取,使用完畢后將連接資源歸還給數(shù)據(jù)源
常見(jiàn)的數(shù)據(jù)源(連接池):DBCP C3P0 BoneCP Druid等.
開發(fā)步驟:
1) 導(dǎo)入數(shù)據(jù)源的坐標(biāo)和數(shù)據(jù)庫(kù)驅(qū)動(dòng)坐標(biāo)
2) 創(chuàng)建數(shù)據(jù)源對(duì)象
3) 設(shè)置數(shù)據(jù)源的基本連接數(shù)據(jù)
4) 使用數(shù)據(jù)源獲取連接資源和歸還連接資源
2.2 數(shù)據(jù)源的手動(dòng)創(chuàng)建方式
1_C3P0連接池的創(chuàng)建
1)導(dǎo)入c3p0的坐標(biāo)(依賴)
<!--pom配置中引入c3p0坐標(biāo)(依賴)-->
<!--c3p0連接池-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</actifactId>
<version>0.9.1.2</version>
</dependency>
2)導(dǎo)入數(shù)據(jù)庫(kù)mysql驅(qū)動(dòng)坐標(biāo)
<!--pom配置中引入mysql驅(qū)動(dòng)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</actifactId>
<version>5.1.39</version>
</dependency>
3)創(chuàng)建c3p0連接池對(duì)象
@Test
public void testC3P0() throws Exception{
//創(chuàng)建數(shù)據(jù)源
ComboPoolDataSource dataSource = new CombopoolDataSource();
//設(shè)置數(shù)據(jù)庫(kù)連接參數(shù)
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("root");
//獲得連接對(duì)象
Connection conn = dataSource.getConnection();
System.out.printLn(conn);
}
2_Druid連接池的創(chuàng)建
1)、導(dǎo)入Druid連接池坐標(biāo)
<!-- Druid連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
2)、導(dǎo)入mysql數(shù)據(jù)庫(kù)驅(qū)動(dòng)坐標(biāo)
<!-- mysql驅(qū)動(dòng) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
3)、創(chuàng)建Druid連接池
@Test
public void testDruid() throws Exception {
//創(chuàng)建數(shù)據(jù)源
DruidDataSource dataSource = new DruidDataSource();
//設(shè)置數(shù)據(jù)庫(kù)連接參數(shù)
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");
//獲得連接對(duì)象
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
3、提取jdbc.properties配置文件,并讀取配置文件創(chuàng)建連接池
//提取配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
//使用ResourceBundle加載resource文件 ResourceBundle資源捆綁
@Test
public void testByProperties() throws Exception{
//加載類路徑下jdbc.properties
ResourceBundle rb = ResourceBundle.getBundle("jdbc");
//創(chuàng)建連接池
//c3p0數(shù)據(jù)源
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//druid數(shù)據(jù)源
DruidDataSource dataSource = new DruidDataSource();
//設(shè)置數(shù)據(jù)源屬性
dataSource.setDriverClass(rb.getString("jdbc.driver"));
dataSource.setJdbcUrl(rb.getString("jdbc.url"));
dataSource.setUser(rb.getString("jdbc.username"));
dataSource.setPassword(rb.getString("jdbc.password"));
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
2.3Spring配置數(shù)據(jù)源
Spring配置數(shù)據(jù)源就是將DataSource的創(chuàng)建全交給Spring容器去完成
- DataSource有參/無(wú)參構(gòu)造方法,Spring默認(rèn)是通過(guò)無(wú)參構(gòu)造方法實(shí)例化對(duì)象
- DataSource set方法進(jìn)行字符串注入
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
測(cè)試從容器中獲取數(shù)據(jù)源連接
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource)applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection);
2.4抽取jdbc配置文件
applicationContext.xml加載jdbc.properties配置文件獲得連接信息。
首先,需要引入context命名空間和約束路徑:
命名空間:xmlns:context="http://www.springframework.org/schema/context"
約束路徑:http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
三,Spring注解開發(fā)
注解的時(shí)候, set方法可以省略
3.1 Spring原始注解
Spring原始注解主要是代替xml中<bean>的配置
| 注解 | 說(shuō)明 |
|---|---|
| @Component | 使用在類上 用于實(shí)例化Bean |
| @Controller | 使用在web層類上 用于實(shí)例化Bean |
| @Service | 使用在service層 用于實(shí)例化bean |
| @Repository | 使用在dao層上 用于實(shí)例化bean,實(shí)現(xiàn)類只有一個(gè)的話,不用注入id |
| @Autowired | 使用在字段上用于根據(jù)類型依賴注入,按照數(shù)據(jù)類型從spring匹配 |
| @Qualifier | 結(jié)合@Autowired一起使用,用于根據(jù)名稱進(jìn)行依賴注入,是按照id的值,從容器開始匹配的.實(shí)現(xiàn)類不唯一時(shí)必須結(jié)合@qualifier使用 |
| @Resource | 按照名稱進(jìn)行注入,相當(dāng)于@Autowired+@Qualifier |
| @Value | 注入普通屬性 |
| @Scope | 標(biāo)注Bean的作用范圍 singeton單例 prototype多例 |
| @PostConstruct | 使用在方法上標(biāo)注該方法是bean的初始化方法 |
| @PreDestroy | 使用在方法上標(biāo)注該方法是bean的銷毀方法 |
注意: 使用注解進(jìn)行開發(fā)時(shí),需要在applicationContext.xml中配置組件掃描,作用是指定哪個(gè)包及其子包下的bean需要進(jìn)行掃描以便識(shí)別使用注解配置的類 ,字段 和方法.
<!--注解的組件掃描-->
<context:component-scan base-package="cn.ppvir"/>
注解使用示例
//1.dao層 使用@Component組件或者@Repository表示 需要spring進(jìn)行實(shí)例化
//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save running... ...");
}
}
//2.service層 使用@Component組件或者@Service標(biāo)識(shí) 需要spring進(jìn)行實(shí)例化
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
/*@Autowired
@Qualifier("userDao")*/
@Resource(name="userDao")
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
}
//3.注入
//3.1 userDao注入 使用@Autowired 或者 @Autowired+@Qualifier 或者@Resource
public class UserServiceImpl implements UserService {
/*@Autowired 自動(dòng)注入
@Qualifier("userDao") 限定名稱*/
@Resource(name="userDao") //按照名稱進(jìn)行注入
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
}
//3.2 普通字符串注入 使用@Value
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Value("注入普通數(shù)據(jù)")//普通字符串注入
private String str;
@Value("${jdbc.driver}")//普通字符串注入
private String driver;
@Override
public void save() {
System.out.println(str);
System.out.println(driver);
System.out.println("save running... ...");
}
}
//4.標(biāo)注bean的范圍 單例或者多例 使用@Scope("singleton") 或者 @Scope("prototype")
//5.初始化和銷毀標(biāo)注 使用@PostConstruct @PreDestroy
@PostConstruct
public void init(){
System.out.println("初始化方法....");
}
@PreDestroy
public void destroy(){
System.out.println("銷毀方法.....");
}
3.2 Spring新注解
原始注解不能替代全部xml配置文件,還需要使用注解替代的配置如下:
- 非自定義的bean的配置:
<bean> - 加載properties文件的配置:
<context:property-placeholder location="classpath:jdbc.properties"/> - 組件掃描的配置:
<context:component-scan base-package="cn.ppvir"/> - 引入其他文件:
<import resource="classpath:applicationContext.xml"></import>
| 注解 | 說(shuō)明 |
|---|---|
| @Configuration | 用于指定當(dāng)前類是一個(gè)spring配置類,當(dāng)創(chuàng)建容器是會(huì)從該類上加載注解 |
| @ComponentScan | 用于指定Spring在初始化容器時(shí)要掃的包,作用與在xml配置文件中的<context:component-scan>一樣 |
| @Bean | 使用在方法上,標(biāo)注將該方法的返回值存儲(chǔ)到spring容器中 |
| @PropertySource | 用于加載配置文件中的配置 |
| @Import | 用于導(dǎo)入其他配置類 |
新注解使用示例:
- @Configuration | @ComponentScan | @Import
/*總配置類*/
@Configuration
@ComponentScan("com.itheima")//掃包
@Import({DataSourceConfiguration.class})//加載分配置 數(shù)組形式
public class SpringConfiguration {
}
- @propertySource | @Value
/*分配置類*/
/* 先將配置文件讀取出來(lái), 然后用@value為成員變量注入普通屬性*/
@PropertySource("classpath:jdbc.properties")//讀取配置文件
public class DataSourceConfiguration {
@Value("${jdbc.driver}") // 注入普通屬性
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
- @Bean
@Bean(name="dataSource")//spring會(huì)將當(dāng)前方法的返回值,以指定名稱存儲(chǔ)到spring容器中
public DataSource getDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
}
- 測(cè)試加載核心配置類,創(chuàng)建spring容器
@Test
public void testAnnoConfiguration() throws Exception {
//使用AnnotationConfigApplicationContext 加載
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = (UserService)
applicationContext.getBean("userService");
userService.save();
DataSource dataSource = (DataSource)
applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
四,Spring整合Junit測(cè)試
4.1 原始Junit測(cè)試 spring問(wèn)題
在測(cè)試類中,每個(gè)測(cè)試方法都必須書寫,讀取配置文件和獲取spring容器的代碼
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
以上代碼作用是獲取容器,沒(méi)有會(huì)報(bào)空指針異常.
所以,需要讓springjunit負(fù)責(zé)創(chuàng)建spring容器,但是需要將配置文件的名稱告訴spring,將需要進(jìn)行測(cè)試的bean知己誒在測(cè)試類中進(jìn)行注入
4.2 Spring集成Junit的步驟:
- 導(dǎo)入spring集成Junit的坐標(biāo)
- 使用@Runwith注解替換原來(lái)的運(yùn)行期
- 使用@ContextConfiguration指定配置文件或配置類
- 使用@Autowired注入需要測(cè)試的對(duì)象
- 創(chuàng)建測(cè)試方法進(jìn)行測(cè)試
4.3代碼示例:
- 導(dǎo)入spring集成Junit的坐標(biāo)
<!--此處需要注意的是,spring5 及以上版本要求 junit 的版本必須是 4.12 及以上-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
- 使用@Runwith注解替換原來(lái)的運(yùn)行期
@RunWith(SpringJUnit4ClassRunner.class)//記憶
public class SpringJunitTest {
}
- 使用@ContextConfiguration指定配置文件或配置類
@RunWith(SpringJUnit4ClassRunner.class)
//加載spring核心配置文件
//@ContextConfiguration(value = {"classpath:applicationContext.xml"})
//加載spring核心配置類
@ContextConfiguration(classes = {SpringConfiguration.class})//告訴配置類位置
public class SpringJunitTest {
}
- 使用@Autowired注入需要測(cè)試的對(duì)象
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
@Autowired//直接進(jìn)行注入
private UserService userService;
}
- 創(chuàng)建測(cè)試方法進(jìn)行測(cè)試
/*搭建好測(cè)試以后 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
@Autowired
private UserService userService;
@Test
public void testUserService(){
userService.save();
}
}