Spring配置數據源
數據源(連接池)的作用
數據源(連接池)是提高程序性能如出現的
事先實例化數據源,初始化部分連接資源
使用連接資源時從數據源中獲取
使用完畢后將連接資源歸還給數據源
常見的數據源(連接池):DBCP、C3P0、BoneCP、Druid等
開發步驟
①導入數據源的坐標和數據庫驅動坐標
②創建數據源對象
③設置數據源的基本連接數據
④使用數據源獲取連接資源和歸還連接資源
現在spring項目中的pom中導入jar包坐標

<!-- 導入第三方jar包--> <dependencies> <!-- 導入Spring的jar 包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.3.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--導入數據源連接需要的jar包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency> </dependencies>
手動創建c3p0的數據源

@Test //手動創建c3p0的數據源 public void testTwo() throws Exception { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/book"); dataSource.setUser("zhao"); dataSource.setPassword("123456"); Connection conn = dataSource.getConnection(); System.out.println(conn); conn.close(); }
手動創建Driver數據源

@Test //手動創建Driver數據源 public void TestOne() throws Exception{ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/book"); dataSource.setUsername("zhao"); dataSource.setPassword("123456"); Connection conn = dataSource.getConnection(); System.out.println(conn); conn.close(); }
提取數據庫信息放到配置文件中讀取
上面都是我們手動創建然后配置信息都在java源代碼中這樣會導致以后如果修改數據庫的鏈接信息不方便
后期更改數據庫的要找到源碼修改太麻煩
提取jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/book jdbc.username=zhao jdbc.password=123456
在設置properties的時候,里面的內容不可以加上分號
讀取jdbc.properties配置文件創建連接池
//讀取jdbc.properties配置文件創建連接池 @Test public void TestThree() throws Exception { ResourceBundle rb = ResourceBundle.getBundle("jdbc"); // 指定連接的驅動方式 ComboPooledDataSource dataSource = new ComboPooledDataSource(); 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 conn = dataSource.getConnection(); System.out.println(conn); }
上面都不是Spring的 容器來配置數據源的
下面我們使用spring容器創建數據源
Spring配置數據源
可以將DataSource的創建權交由Spring容器去完成
DataSource有無參構造方法,而Spring默認就是通過無參構造方法實例化對象的
DataSource要想使用需要通過set方法設置數據庫連接信息,而Spring可以通過set方法進行字符串注入
applicationContext.xml
<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>
測試從容器當中獲取數據源
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource dataSource = (DataSource) applicationContext.getBean("dataSource"); Connection connection = dataSource.getConnection(); System.out.println(connection);
上面的方法是沒有抽取jdbc的配置文件,我們將配置文件抽取到properties文件中
將數據源的配置抽取到properties中,抽取到xml解析比較費勁,properties是鍵值對的方式,
Spring容器提取配置文件到Properties中然后
抽取jdbc配置文件
applicationContext.xml加載jdbc.properties配置文件獲得連接信息。
首先,需要引入context命名空間和約束路徑:
命名空間首先要在applicaltionContext.xml中創建
需要引入context命名空間和約束路徑: 命名空間:xmlns:context="http://www.springframework.org/schema/context" 約束路徑:http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
命名空間的創建在beans中的xmlns中復制第一個的xmlns人然后改成xmlns:context
applicationContext.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="classpath:jdbc.properties"/> <!--加載jdbc的配置文件--> <!-- <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 這里是使用cp30--> <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"><!--這是使用druid數據源連接--> <property name="driverClassName" value="${jdbc.driver}"/> <!--這里指定的name值是你的讀取jdbc.properties配置文件方法中的set后面的內容--> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/book jdbc.username=zhao jdbc.password=123456
Spring容器加載properties文件
<context:property-placeholder location="classpath:xx.properties"/> <property name="" value="${key}"/
實現:
//Spring容器創建Druid的數據源 @Test public void TestFive() throws SQLException { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource bean = app.getBean(DataSource.class); Connection connection = bean.getConnection(); System.out.println(connection); }
Spring注解開發
spring的注解分為原始注解和新注解
Spring原始注解:
Spring是輕代碼重配置的框架,配置比較繁重,影響開發效率,所以注解開發是一種趨勢,注解代替Xml配置文件可以簡化配置,提高開發效率
Spring原始注解主要是替代的配置
注解 | 說明 |
@Component | 使用在類上用於實例化Bean |
@Controller | 使用在web層類上用於實例化Bean |
@Service | 使用在Service層類上用於實例化Bean |
@Repository | 使用在dao層類上用於實例化Bean |
@Autowired | 使用在字段上用於根據類型依賴注入 |
@Qualifier | 結合@Autowired一起使用用於根據名稱進行依賴注入 |
@Resource | 相當於@Autowired+@Qualifier,按照名稱進行注入 |
@Value | 注入普通屬性 |
@Scope | 標注Bean的作用范圍 |
@PostConstruct | 使用在方法上標注該方法是Bean的初始化方法 |
@PreDestroy | 使用在方法上標注該方法是Bean的銷毀方法 |
注意:
使用注解進行開發時,需要在applicationContext.xml中配置組件掃描,作用是指定哪個包及其子包下的Bean需要
進行掃描以便識別使用注解配置的類、字段和方法。
首先我們對比下Spring的依賴注入使用注解和不使用注解的方法
Spring的依賴注入
在創建完UserServiceImpl.java和UserDaoImpl.java之后我們要在配置文件applicationContext.xml中進行對應的Bean對象的創建和注入
UserDaoImpl.java
public class UserDaoImpl implements UserDao { public void save() { System.out.println("come on Running...."); } }
UserServiceImpl.java
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void save() { userDao.save(); } }
applicationContext.xml
<bean id="userDao" class="com.spring.Dao.Impl.UserDaoImpl"></bean> <!--創建UserDaoImpl的Bean對象--> <bean id="userService" class="com.spring.service.Impl.UserServiceImpl"><!--創建UserServiceImpl的Bean對象--> <property name="userDao" ref="userDao"/><!--將UserDaoImpl的bean對象注入到UserService中--> </bean>
這樣配置起來是很麻煩的
Spring的注解注入
我們可以將Spring的要在applicationContext.xml中配置的內容全部都通過注解來解決
@Component 實例化bean對象
UserDaoImpl.java
@Component("userDao") //實例化bean對象,並且這個bean對象的id是userDao // 相當於在applicationContext.xml中配置這個<bean id="userDao" class="com.spring.Dao.Impl.UserDaoImpl"></bean> <!--創建UserDaoImpl的Bean對象--> public class UserDaoImpl implements UserDao { public void save() { System.out.println("come on Running...."); } }
userServiceImpl.java
@Component("userService") // 實例化Bean對象,這個bean對象的id是userService public class UserServiceImpl implements UserService { @Autowired // 類型注入 將這個參數注入到此處 @Qualifier("userDao") // 依賴注入,注入userDao這個bean這個是寫你的要注入你的bean的id 你要注入userDaoImpl的bean 它的id是userDao private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void save() { userDao.save(); } }
如果只配置了上面的注解,沒有聲明注解的作用的范圍也是不可以使用的
Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@23ab930d: startup date [Tue Dec 15 15:42:08 CST 2020]; root of context hierarchy
十二月 15, 2020 3:42:08 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
上面的報錯就是未配置注解掃描
配置注解掃描要在applicationContext.xml中配置
<!-- 配置注解掃描--> <context:component-scan base-package="com.spring"></context:component-scan>
所以我們在applicationContext.xml的配置文件中設置這個 所以即使不在我們也要創建一個配置文件
因為我們在運行的時候也會通過這個配置文件運行的
public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService bean = app.getBean(UserService.class); bean.save(); }
使用@Component或@Repository標識UserDaoImpl需要Spring進行實例化。
//@Component("userDao") //實例化bean對象,並且這個bean對象的id是userDao @Repository("userDao") // 使用作用的dao上的bean實例化注解 // 相當於在applicationContext.xml中配置這個<bean id="userDao" class="com.spring.Dao.Impl.UserDaoImpl"></bean> <!--創建UserDaoImpl的Bean對象--> public class UserDaoImpl implements UserDao { public void save() { System.out.println("come on Running...."); } }
其實我們在使用注解的@Component @Repository @Service @ Controller 這些注解作用都一樣只不過是作用在不同的區域更規范,如果不規范也是可以互相使用的
Bean的依賴注入
如果我們要進行bena的依賴注入 可以使用
使用@Autowired或者@Autowired+@Qulifier或者@Resource進行userDao的注入
@Repository("userService") public class UserServiceImpl implements UserService { // @Autowired // 類型注入 將這個參數注入到此處 // @Qualifier("userDao") // 依賴注入,注入userDao這個bean這個是寫你的要注入你的bean的id 你要注入userDaoImpl的bean 它的id是userDao @Resource(name = "userDao") private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void save() { userDao.save(); } }
使用@Value進行字符串的注入
@Value("laowang") // value進行普通賦值 private String name;
使用@Scope標注Bean的范圍
//@Scope("prototype") @Scope("singleton") public class UserDaoImpl implements UserDao { //此處省略代碼 }
使用@PostConstruct標注初始化方法,使用@PreDestroy標注銷毀方法
@PostConstruct public void init(){ System.out.println("初始化方法...."); } @PreDestroy public void destroy(){ System.out.println("銷毀方法....."); }
Spring新注解
使用上面的注解還不能全部替代xml配置文件,還需要使用注解替代的配置如下:
非自定義的Bean的配置:
加載properties文件的配置:context:property-placeholder
組件掃描的配置:context:component-scan
引入其他文件:
注解 | 說明 |
@Configuration | 用於指定當前類是一個 Spring 配置類,當創建容器時會從該類上加載注解 |
@ComponentScan | 用於指定 Spring 在初始化容器時要掃描的包。 作用和在 Spring 的 xml 配置文件中 |
@Bean | 使用在方法上,標注將該方法的返回值存儲到 Spring 容器中 |
@PropertySource | 用於加載.properties 文件中的配置 |
@Import | 用於導入其他配置類 |
@Configuration 指定當前類是spring的核心配置文件
@ ComponentScan("組件的名稱") // 組件掃描
@Bean("dataSource") // Spring會將當前方法的返回值以指定名稱存儲到Spring容器中
@Import({類})
@Configuration //指定當前類是spring的核心配置文件 @ComponentScan("com.spring") // 組件掃描 相當於 <context:component-scan base-package="com.spring"></context:component-scan> @PropertySource("classpath:jdbc.properties") // 加載配置文件 <context:property-placeholder location="classpath:jdbc.properties"/> public class SpringConfiguration { @Bean("dataSource") // Spring會將當前方法的返回值以指定名稱存儲到Spring容器中 public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/book"); dataSource.setUser("zhao"); dataSource.setPassword("123456"); return dataSource; } }
eg:
spring的核心配置類
SpringConfiguration.java
@Configuration //指定當前類是spring的核心配置文件 @ComponentScan("com.spring") // 組件掃描 相當於 <context:component-scan base-package="com.spring"></context:component-scan> @Import(DataSourceConfiguration.class) // 將DataourceConfigureation類加載到當前類中 public class SpringConfiguration { }
DataSourceConfiguration.java
@PropertySource("classpath:jdbc.properties") // 加載配置文件 <context:property-placeholder location="classpath:jdbc.properties"/> public class DataSourceConfiguration { // @value進行字符串值的注入 對配置文件的值進行賦值 @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將此方法放到speing容器后后面可以直接使用getBean然后獲取方法名 @Bean("dSource") // Spring會將當前方法的返回值以指定名稱存儲到Spring容器中 public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } }
main
public static void main(String[] args) throws SQLException { // ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class); //獲取核心配置類 UserService bean = app.getBean(UserService.class); bean.save(); DataSource dataSource = (DataSource) app.getBean("dSource"); // 獲取@Bean注解生成的spring容器內的方法 Connection connection = dataSource.getConnection(); System.out.println(connection); }
上面使用這種新注解的方式就徹底放棄了xml配置文件了
Spring整合Junit
1 原始Junit測試Spring的問題
在測試類中,每個測試方法都有以下兩行代
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); IAccountService as = ac.getBean("accountService",IAccountService.class);
這兩行代碼的作用是獲取容器,如果不寫的話,直接會提示空指針異常。所以又不能輕易刪掉。
上述問題解決思路
讓SpringJunit負責創建Spring容器,但是需要將配置文件的名稱告訴它
將需要進行測試Bean直接在測試類中進行注入
Spring集成Junit步驟
①導入spring集成Junit的坐標
②使用@Runwith注解替換原來的運行期
③使用@ContextConfiguration指定配置文件或配置類
④使用@Autowired注入需要測試的對象
⑤創建測試方法進行測試
Spring集成Junit代碼實現
1: ①導入spring集成Junit的坐標
<!--此處需要注意的是,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注解替換原來的運行期
使用@Runwith注解替換原來的運行期
@RunWith(SpringJUnit4ClassRunner.class) // 測試 //@ContextConfiguration("classpath:applicationContext.xml") //告訴它測試的文件是哪個 @ContextConfiguration(classes = {SpringConfiguration.class}) // 測試核心配置類 public class springTest { @Autowired // 注入要測試的 對象 private UserService userService; @Test public void save(){ userService.save(); } }
③使用@ContextConfiguration指定配置文件或配置類
@RunWith(SpringJUnit4ClassRunner.class) // 測試 //@ContextConfiguration("classpath:applicationContext.xml") //加載spring核心配置文件 @ContextConfiguration(classes = {SpringConfiguration.class}) // 加載測試核心配置類 public class springTest { @Autowired // 注入要測試的 對象 private UserService userService; @Test public void save(){ userService.save(); } }
④使用@Autowired注入需要測試的對象
@Autowired // 注入要測試的 對象 private UserService userService;
⑤創建測試方法進行測試
@Test public void save(){ userService.save(); }