Spring (2)框架

Spring次日筆記java

1. 使用註解配置Spring入門

1.1. 說在前面

學習基於註解的IoC配置,你們腦海裏首先得有一個認知,即註解配置和xml配置要實現的功能都是同樣的,都是要下降程序間的耦合。只是配置的形式不同。mysql

關於實際的開發中到底使用xml仍是註解,每家公司有着不一樣的使用習慣。因此這兩種配置方式咱們都須要掌握。web

 

   基於註解配置的方式也已經逐漸代替xml。因此咱們必需要掌握使用註解的方式配置Springspring

 

1.2. 配置步驟

注意:Eclipse須要先安裝了STS插件,或者使用STS開發工具建立項目。sql

1.2.1. 第一步:拷貝必備jar包到工程的lib目錄。

注意:在基於註解的配置中,咱們還要多拷貝一個aopjar包。以下圖:數據庫

 

 

 

1.2.2. 第二步:在類的根路徑下建立一個任意名稱的xml文件(不能是中文)

 

 

注意:基於註解整合時,Spring配置文件導入約束時須要多導入一個context名稱空間下的約束session

<?xml version="1.0" encoding="UTF-8"?>app

<beans xmlns="http://www.springframework.org/schema/beans"框架

xmlns:p="http://www.springframework.org/schema/p"dom

xmlns:context="http://www.springframework.org/schema/context"

    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.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context.xsd

">

</beans>

1.2.3. 步:建立一個服務類

建立一個測試的服務類,而且加入使用@Component註解聲明該類容許注入到Spring容器

package com.zj.spring.service;

 

import org.springframework.stereotype.Component;

 

//1.使用註解配置,須要將啓動是就建立對象的類表示爲組件類

@Component

public class CustomerService {

 

public void save(){

System.out.println("-保存數據-");

}

 

}

 

 

1.2.4. 第四步在spring的配置文件加入掃描註解

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:context="http://www.springframework.org/schema/context"

    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.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context.xsd">

 

   <!-- 聲明掃描包以及子包的類。若是發現有組件註解的類,就建立對象,並加入到容器 -->

   <context:component-scan base-package="cn.zj.spring"></context:component-scan>

</beans>

 

1.2.5. 第五步:測試調用代碼

package com.zj.spring.test;

 

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.zj.spring.service.CustomerService;

 

public class CustomerServiceTest {

 

public static void main(String[] args) {

//CustomerService cs=new CustomerService();

ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

 

CustomerService customerService = context.getBean("customerService",CustomerService.class);

customerService.save();

context.close();

}

}

 

--測試結果,若是能夠調用服務方法,測試成功

 

1.2.6. 設置註解掃描的組件的名稱

默認狀況下, 被註解@Component 掃描的類的名稱就是當前類名的首字母小寫名稱,開發者能夠自定義組件的名稱

/* 使用註解方式配置IOC

@Component 說明當前類被Spring管理,Spring框架啓動的時候就會建立此類的對象

設置當前Bean的名稱

默認當前Bean的名稱就是簡單類名的 首字母小寫 customerService

value 屬性能夠自定義組件的名稱 等價於 <bean id/name="bean名稱">

@Component(value="service")

簡寫,能夠省略value

@Component("service")

 

*/

@Component("service")

public class CustomerService {

public void save() {

System.out.println("-保存數據-");

}

}

 

2. Spring經常使用註解說明

2.1. 用於對象的註解-IOC相關注解

咱們將用於被掃描建立對象的註解,統稱爲組件註解

 

組件包括:@Component@Controller@Service@Repository

 

組件註解的功能都是標識類爲注解的組件類,啓動Spring框架的程序時,聲明將這些組件類注入到Spring容器裏面。意味着,只有加了這四個註解任何一個註解的類,在程序啓動的時候,Spring就經過配置文件指定的路徑將該路徑下的全部帶組件註解的類建立對象而且放在容器裏面。

 

功能相似原來配置文件的<bean>標籤

 

問題:明明一個@Component註解就能夠知足了掃描的須要,爲何要有四個呢?

答:其實Spring初版註解的實現(spring 2.5),就是使用一個@Component。從3.0之後,做者認爲根據分層的須要,把它拆成了四個。爲了可讓開發人員,可見便可得,一看到註解,當即知道類的性質。因此分紅了四個

 

@Controller:用於聲明表示層的組件註解

@Service:用於聲明服務層的組件註解

@Repository:用於聲明持久層的組件註解

@Component:用於聲明三層之外的組件註解

 

 

問題:那麼,這四個註解交換使用會報錯嗎。如:持久層,我放@Service標記。

答:處理@ControllerSpringMVC裏面有強制的要求,SpringMVC的表示層必須使用@Controller組件註解。其餘狀況,用亂了是不會報錯的,不過咱們必須不能用亂。不遵照規範,否則別人沒法跟你一塊兒開發了。

 

 

2.1.1. @Scope用於設置對象的生命週期註解

Xml配置須要配置對象的做用範圍

<bean id="someBean" class="..."  scope="做用範圍"></bean>

 

若是使用註解配置bean,那麼bean的做用範圍也須要使用註解配置

@Scope("做用範圍")

singleton

 

 單例 ,在Spring IoC容器中僅存在一個Bean實例 (默認的scope

prototype

多例 ,每次從容器中調用Bean時,都返回一個新的實例,即每次調用getBean()時 ,至關於執行new XxxBean()

request

用於web開發,將Bean放入request範圍 ,request.setAttribute("xxx") , 在同一個request 得到同一個Bean

 

session

用於web開發,將Bean 放入Session範圍,在同一個Session 得到同一個Bean

 

package cn.zj.spring.controller;

 

import javax.annotation.Resource;

 

import org.springframework.context.annotation.Scope;

import org.springframework.stereotype.Controller;

 

import cn.zj.spring.service.CustomerService;

@Controller("customerController")

@Scope("prototype")

public class CustomerController {

 

//直接字段注入,不須要setter方法

//@Resource //按照類型注入

@Resource(name="customerService")//類型+id

private CustomerService customerService;

 

public void save() {

//調用服務的save方法

customerService.save();

}

}

 

 

在開發中主要使用 scope="singleton"scope="prototype"

對於MVC中的Action/Controller使用prototype類型,其餘使用singleton

 

 

2.1.2. @PostConstruct @PreDestroy初始化和銷燬方法註解

xml配置中能夠配置對象的初始化方法和銷燬方法

<bean id="someBean" class="cn.zj.spring.domain.SomeBean" 

init-method="init"

destroy-method="destory"></bean> 

若是使用註解配置bean,那麼bean的做用範圍也須要使用註解配置

@PostConstruct // 至關於<bean init-method="init" />

public void init() {

System.out.println("初始化方法執行了");

}

@PreDestroy// 至關於<bean destroy-method="destory" />

public void destory() {

System.out.println("銷燬方法執行了");

}

 

2.2. 用於依賴注入的註解

回顧:XML配置文件使用<property name=」」 ref=」」>實現注入的。經過注入註解也能夠實現。

 

Spring提供了兩套註解能夠解決依對象依賴注入的方案

 

1,@Autowired +@Qualifier():Spring定義的標籤

 

2,@Resouce:J2EE的規範

2.2.1. @Autowired註解

 

@Autowired註解:用於給引用注入容器的對象。

  1. @Autowired標籤貼在字段或者setter方法上
  2. 默認狀況下@Autowired標籤必需要能找到對應的對象,不然報錯。不過,可以使用required=false來避免該問題:@Autowired(required=false)
  3. @Autowiredbean的方式:

(1) 首先按照依賴對象的類型找,若是找到則使用setter方法或者字段直接注入;

(2) 若是Spring上下文中找到多個匹配的類型,再按照名字去找,若是沒有匹配則報錯;

(3) 能夠經過使用@Qualifier("otherBean")標籤來規定依賴對象按照beanid+類型去找

 

使用@Autowired注入的三種狀況

2.2.1.1. 在字段上面注入

package cn.zj.spring.controller;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

 

import cn.zj.spring.service.CustomerService;

//表示層使用@Controller

//若是組件註解不聲明對象名,默認使用默認命名法,

//所謂的默認命名就是,將類的首字符小寫做爲類的對象名

//組件註解

 //屬性 value:做用用於指定該類對象的自定義對象名

@Controller("customerController")

public class CustomerController {

 

//直接字段注入,不須要setter方法

@Autowired

private CustomerService customerService;

 

/*public void setCustomerService(CustomerService customerService) {

this.customerService = customerService;

}*/

public void save() {

//調用服務的save方法

customerService.save();

}

}

 

 

2.2.1.2. 在方法上面注入

package cn.zj.spring.controller;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

 

import cn.zj.spring.service.CustomerService;

 

//表示層使用@Controller

//若是組件註解不聲明對象名,默認使用默認命名法,

//所謂的默認命名就是,將類的首字符小寫做爲類的對象名

//組件註解

   //屬性 value:做用用於指定該類對象的自定義對象名

@Controller(value="customerController")

public class CustomerController {

 

 

private CustomerService customerService=null;

 

//注意,若是將@Autowired方法方法上面,意思就是將對象注入到該的方法的參數

//意味着:Spring會自動根據參數的CustomerService類型匹配容器中對應的對象給它

//注意:可以使用@Autowired註解的方法是必須有參數的

@Autowired

public void setCustomerService(CustomerService customerService) {

//問題:加了@Autowired的方法在啓動的時候是否執行了?

//答:若是該方法沒有執行,那麼this.customerService的對象從哪裏來呢?

//加了@Autowired在啓動項目的時候是必須自動執行的

System.out.println("-setCustomerService已經被執行-");

this.customerService = customerService;

}

 

public void save(){

System.out.println("-保存客戶-CustomerAction");

customerService.save();

}

 

}

 

 

2.2.1.3. 在構造方法上面注入

package cn.zj.spring.controller;

 

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.stereotype.Controller;

 

import cn.zj.spring.service.CustomService;

 

@Controller

public class CustomController {

 

 

private CustomService service;

 

 

 

/*

 * 方式三 : 構造器注入

 * 使用註解的IOC建立bean的狀況下

 * 默認bean中有什麼樣的構造器,spring就調用那個構造器去建立對應的bean對象

 * 而且會自動注入 構造器中對應類型參數的對象

 *

 * 問題: 若是構造函數的參數類型對應的bean有多個,會拋出異常

 * org.springframework.beans.factory.NoUniqueBeanDefinitionException 不是惟一的bean異常

 * 解決方案: 在參數前面 使用 @Qualifier("service1") 註解

 * 從多個bean 獲取指定 id 對應的bean便可

 */

public CustomController(@Qualifier("service1") CustomService service) {

this.service = service;

}

 

 

public void save() {

service.save();

}

 

}

 

 

 

 

 

 

 

2.2.2. @Qualifier註解

@Qualifier註解:用於指定注入的對象名,使用@Autowired注入對象時,@Autowired沒有指定對象名的屬性,只能經過@Qualifier字段容器中對象名

 

屬性

  value:指定注入Spring容器中對應對象名的對象給引用。

 

@Controller("customerController")

public class CustomerController {

 

//直接字段注入,不須要setter方法

@Autowired

@Qualifier(value="customerService")

private CustomerService customerService;

 

public void save() {

//調用服務的save方法

customerService.save();

}

}

 

2.2.3. @Resource註解

@Resource註解是Spring框架支持Sun官方制定的JSR-250標準注入對象的實現

 

JSR-250就是Sun公司制定,對注入的對象的標準。

 

 

@Resource 功能等同 @Autowired + @Qualifier ,等同配置文件標籤 <proprty name=」...」 ref=」...」>

@Resource註解:用於給引用注入容器的對象,能夠經過name屬性指定對象名

 

注意事項:@Resource只能使用字段和setter方法,不能注入構造方法

 

package cn.zj.spring.controller;

 

import javax.annotation.Resource;

 

import org.springframework.stereotype.Controller;

 

import cn.zj.spring.service.CustomerService;

@Controller("customerController")

public class CustomerController {

 

//直接字段注入,不須要setter方法

//@Resource //按照類型注入

@Resource(name="customerService")//類型+id

private CustomerService customerService;

 

public void save() {

//調用服務的save方法

customerService.save();

}

}

 

 

2.2.4. 依賴注入註解所在的包的位置

除了@Resource註解是Java官方的標準,內置在JDK裏面之外,Spring內置實現的註解聲明放在spring-beans-5.0.5.RELEASE.jar裏面。以下圖所示:

 

 

2.2.5. @Value註解

<value>

//value只能設置,標量類型=基礎數據類型+包裝類+String

@Value註解:注入基本數據類型以及它們的包裝類String類型數據的支持${}注入Properties文件的鍵值對,等同 <proprty name=」...」 value=」${Key}」>

 

屬性:

  value注入基本數據類型和String類型數據的

2.2.5.1. 案例代碼

package cn.zj.spring.dao.impl;

 

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Repository;

 

import cn.zj.spring.dao.UserDao;

import cn.zj.spring.pojo.User;

 

 

@Repository

public class UserDaoImpl implements UserDao {

 

/**

 * @Value(value="")

 * 能夠從Spring容器讀取 .properties 配置文件內容

 * value :配置文件的對應的key -->使用 ${key} 獲取

 * 程序運行中自動將 properties 對應key的獲取出來設置給字段

 *

 */

 

//等價 <property name="driverClassName" value="${jdbc.driverClassName}">

@Value("${jdbc.driverClassName}")

private String driverClassName;

 

@Value("${jdbc.url}")

private String url;

 

@Value("${jdbc.username}")

private String username;

 

@Value("${jdbc.password}")

private String password;

 

//@Value("${jdbc.maxActive}")

@Value("100") //開發者也手動賦值

private String maxActive;

 

 

@Override

public void insert(User user) {

System.out.println(driverClassName);

System.out.println(url);

System.out.println(username);

System.out.println(password);

System.out.println(maxActive);

 

}

}

 

 

 

 

3. 模擬註冊功能(使用註解方式)

3.1. DAO層代碼

//@Component("userDao")

@Repository("userDao")

public class UserDaoImpl implements UserDao {

@Override

public void insert(User user) {

System.out.println("註冊的Dao方法執行");

}

}

 

3.2. Service層代碼

@Service("userService")

public class UserServiceImpl implements UserService {

 

/*@Autowired

@Qualifier("userDao")*/

 

@Resource(name="userDao")

private UserDao dao;

 

@Override

public void register(User user) {

dao.insert(user);

}

//由於要用

public void setDao(UserDao dao) {

this.dao = dao;

}

}

3.3. 表現層代碼

@Controller

public class UserController {

/*@Autowired

@Qualifier("userService")*/

@Resource(name="userService")

private UserService service;

 

public void register(User user) {

 

service.register(user);

}

}

 

3.4. 測試代碼

public class UserServletTest {

 

@Test

public void testSpring() throws Exception { //建立用戶對象:模擬接受用戶參數,封裝對象的過程

User user = new User();

user.setUsername("張三");

user.setPassword("admin");

        UserController controller = context.getBean("userController",CustomerController.class);

//執行註冊操做

controller.register(user);

}

}

 

3.5. applicationContext.xml

配置文件(只須要配置一個包掃描便可)

<!-- 配置包掃描

cn.zj.spring : 此包以及子包所有被掃描

 -->

<context:component-scan base-package="cn.zj.spring"/>

 

 

 

4. 純註解配置

4.1. 問題

咱們發現,之因此咱們如今離不開xml配置文件,是由於咱們有一句很關鍵的配置:

<!-- 告知spring框架在,讀取配置文件,建立容器時,掃描註解,依據註解建立對象,並存入容器中 -->

<context:component-scan base-package="cn.zj.spring"></context:component-scan>

若是他要也能用註解配置,那麼咱們就能夠脫離xml文件了。

 

經過@Configuration註解和@ComponentScan註解

 

 

替換XML配置文件的

@Configuration註解

 

@Configuration配置類註解,在純註解配置中,類加了該註解,就意味着該類是Spring的配置類。該類的功能就是用於替代原來的XML配置文件。

 

做用:

用於指定當前類是一個spring配置類,當建立容器時會從該類上加載註解。獲取容器時須要使用AnnotationConfigApplicationContext(@Configuration註解的類.class)

 

@ComponentScan註解

 

@ComponentScan註解掃描類,做用就是配置掃描Spring組件類的路徑。功能等同原來配置文件的

--做用:

用於指定spring在初始化容器時要掃描的包。做用和在springxml配置文件中的:

<context:component-scan base-package="cn.zj.spring"/>是同樣的。

--屬性:

basePackages:用於指定要掃描的包。和該註解中的value屬性做用同樣。

 

@PropertySource註解

 

做用:

用於加載.properties文件中的配置。例如咱們配置數據源時,能夠把鏈接數據庫的信息寫到properties配置文件中,就可使用此註解指定properties配置文件的位置。

屬性:

value[]:用於指定properties文件位置。若是是在類路徑下,須要寫上classpath:

 

@Bean註解

 

做用:

該註解只能寫在方法上,使用此方法建立一個對象,而且放入spring容器。它就至關於咱們以前在xml配置中介紹的<bean標籤>

 

屬性:

name:給當前@Bean註解方法建立的對象指定一個名稱(beanid)。

 

@Import註解

 

做用:

用於導入其餘配置類,在引入其餘配置類時,能夠不用再寫@Configuration註解。固然,寫上也沒問題。

<import >

屬性:

value[]:用於指定其餘配置類的字節碼。

 

 

4.2. 示例代碼

4.2.1. 簡單入門

4.2.1.1. 說明

需求:經過一個簡單的入門示例,實現建立一個配置類使用@Configuration註解@ComponentScan註解替換xml文件。

 

4.2.1.2. 配置步驟

 

 

4.2.1.2.1. 第一步:建立一個Java項目

建立一個Java項目,導入必須的jar包以及編寫好須要的類結構。代碼目錄以下:

 

 

4.2.1.2.2. 第三步:編寫配置類代碼

--經過該配置類的代碼替換掉Spring配置文件

package cn.zj.spring.config;

 

import javax.sql.DataSource;

 

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

 

import com.alibaba.druid.pool.DruidDataSource;

 

/*

 * @Configuration

 * 說明把當前類當作成Spring框架的配置文件

 * @ComponentScan

 *  配置註解包掃描的位置

 * @PropertySource("classpath:db.properties")

 *  讀取.peroperties 後綴的配置文件

 */

 

@Configuration

//@ComponentScan(basePackages= {"cn.zj.spring.action","cn.zj.spring.service","cn.zj.spring.dao"})

@ComponentScan("cn.zj.spring")

@PropertySource("classpath:db.properties")

public class SpringConfig {

 

 

/**

 * @Value(value="")

 * 能夠從Spring容器讀取 .properties 配置文件內容

 * value :配置文件的對應的key -->使用 ${key} 獲取

 * 程序運行中自動將 properties 對應key的獲取出來設置給字段

 *

 */

 

//等價 <property name="driverClassName" value="${jdbc.driverClassName}">

@Value("${jdbc.driverClassName}")

private String driverClassName;

 

@Value("${jdbc.url}")

private String url;

 

@Value("${jdbc.username}")

private String username;

 

@Value("${jdbc.password}")

private String password;

 

@Value("${jdbc.maxActive}")

private Integer maxActive;

 

 

//<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"

   //init-method="init" destroy-method="close">

@Bean(name="dataSource",initMethod="init",destroyMethod="close")

public DataSource getDataSource() {

DruidDataSource dataSource = new DruidDataSource();

dataSource.setDriverClassName(driverClassName);

dataSource.setUrl(url);

dataSource.setUsername(username);

dataSource.setPassword(password);

dataSource.setMaxActive(maxActive);

return dataSource;

}

 

}

 

 

4.2.1.2.3. 第四步:編寫測試代碼

package cn.zj.spring.test;

 

import java.sql.Connection;

 

import javax.sql.DataSource;

 

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

import cn.zj.spring.config.SpringConfig;

 

public class SpringTest {

 

@Test

public void testName() throws Exception {

 

// 1.讀取 xml 配置文件,啓動框架,建立Spring容器對象

//ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

 

// 1. 讀取SpringConfig 類配置文件,啓動動框架,建立Spring容器對象

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

 

//2. 獲取 鏈接池對象

DataSource dataSource = context.getBean("dataSource", DataSource.class);

 

//2.1獲取數據庫鏈接對象

Connection conn = dataSource.getConnection();

 

System.out.println(conn);

}

}

 

 

--測試結果,輸出組件類調用方法的輸出值。配置成功

 

 

5. Spring的測試

5.1. 傳統的測試

存在問題:

1,每一個測試都要從新啓動Spring容器,啓動容器的開銷大,測試效率低下。

2,不該該是測試代碼管理Spring容器,應該是Spring容器在管理測試代碼。

 

 

5.2. 正確使用Spring的測試

 

 

5.3. 如何使用Spring測試

5.3.1. 導入spring測試的jar

 

 

Spring測試必須保證Eclipse的單元測試的最低版本是 4.12版本,若是使用的Eclipse版本很低,那麼單元測試版本可能低於4.12,那麼須要開發者手動導入單元測試的jar

 

若是使用Spring方式測試,必須使用兩個註解

 

@RunWith註解

表示先啓動Spring容器,把junit運行在Spring容器中

@ContextConfiguration註解

從哪裏加載資源文件,默認從src(源目錄)下面加載

 

5.3.2. 案例代碼

package cn.zj.spring.test;

 

import static org.junit.Assert.*;

 

import javax.annotation.Resource;

import javax.swing.Spring;

 

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

import cn.zj.spring.config.SpringConfig;

import cn.zj.spring.service.CustomerService;

 

//表示先啓動Spring容器,把junit運行在Spring容器中

@RunWith(SpringJUnit4ClassRunner.class)

//表示從哪裏加載資源文件,默認從src(源目錄)下面加載

@ContextConfiguration("classpath:applicationContext.xml")

public class CustomerServiceTest {

 

@Resource

ApplicationContext context;

 

@Test

public void testSpring() throws Exception {

//1.獲取Spring容器對象

//AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(「applicationContext.xml」);

 

 

//2.獲取CustomerController對象

CustomerService controller = context.getBean("customerService",CustomerService.class);

 

//執行保存方法

controller.save();

}

}

 

 

5.3.3. 純註解方式的配置

 

@ContextConfiguration()

 classes 屬性: 讀取spring的純java配置文件

package cn.zj.spring.test;

 

import static org.junit.Assert.*;

 

import javax.annotation.Resource;

import javax.swing.Spring;

 

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

import cn.zj.spring.config.SpringConfig;

import cn.zj.spring.service.CustomerService;

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes=Spring.class)

public class CustomerServiceTest {

 

@Resource

ApplicationContext context;

 

@Test

public void testSpring() throws Exception {

//1.獲取Spring容器對象

//AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);

 

 

//2.獲取CustomerController對象

CustomerService controller = context.getBean("customerService",CustomerService.class);

 

//執行保存方法

controller.save();

}

}

 

6. SpringJDBC操做

Spring對象也支持JDBC,JDBC只進行了薄薄的一層封裝

問題: Java開發已經有JDBC,爲何Spring還要支持JDBC操做呢?

最重要的緣由: Spring操做JDBC自動管理事務

 

6.1. 操做步驟

1,建立數據庫 spring_jdbc

2.建立數據表 t_user

CREATE TABLE `t_user` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `name` varchar(20) DEFAULT NULL,

  `email` varchar(50) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.建立對應的domain對象

public class User {

private Integer id;

private String name;

private String email;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

@Override

public String toString() {

return "User [id=" + id + ", name=" + name + ", email=" + email + "]";

}

public User(Integer id, String name, String email) {

super();

this.id = id;

this.name = name;

this.email = email;

}

public User() {

super();

// TODO Auto-generated constructor stub

}

 

}

4.建立DAO

public class UserDaoImpl implements UserDao {

 

@Override

public void save(User user) {

 

}

 

@Override

public void delete(Integer id) {

}

 

@Override

public void update(User user) {

 

}

 

@Override

public User findById(Integer id) {

 

return null;

}

 

@Override

public List<User> list() {

 

return null;

}

}

5.建立Service

public class UserServiceImpl implements UserService {

 

private UserDao dao;

 

@Override

public void save(User user) {

dao.save(user);

}

 

@Override

public void delete(Integer id) {

dao.delete(id);

}

 

@Override

public void update(User id) {

dao.update(id);

}

 

@Override

public User findById(Integer id) {

// TODO Auto-generated method stub

return dao.findById(id);

}

 

@Override

public List<User> list() {

// TODO Auto-generated method stub

return dao.list();

}

 

public void setDao(UserDao dao) {

this.dao = dao;

}

}

6.測試代碼

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

public class UserServiceTest {

 

 

@Resource

private UserService service;

 

@Test

public void testSave() {

 

User user = new User(null, "喬峯", "qf@qq.com");

 

service.save(user);

}

 

@Test

public void testDelete() {

service.delete(3);

}

 

@Test

public void testUpdate() {

User user = new User(2, "段譽", "123123sdfsdf@qq.com");

service.update(user);

}

 

@Test

public void testFindById() {

 

User user = service.findById(1);

System.out.println(user);

 

}

@Test

public void testList() {

 

List<User> users = service.list();

System.out.println(users);

}

}

ApplicationContext.xml配置

<!-- 引入 db.properties配置文件 -->

<context:property-placeholder location="classpath:db.properties"/>

 

<!-- 配置Druid鏈接池 : DataSource 數據源 -->

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" 

destroy-method="close"

>

<!-- setter方法注入屬性值 -->

<property name="driverClassName" value="${jdbc.driverClassName}"/>

<property name="url" value="${jdbc.url}"/>

<property name="username" value="${jdbc.username}"/>

<property name="password" value="${jdbc.password}"/>

<!-- 最大鏈接數 -->

<property name="maxActive" value="${jdbc.maxActive}"/>

</bean>

 

 

<!-- 配置DAO層 -->

<bean id="userDao" class="cn.zj.spring.dao.impl.UserDaoImpl2">

<!-- setter方法注入數據源:鏈接池 -->

<property name="dataSource" ref="dataSource"/>

</bean>

 

<!-- 配置Service層 -->

<bean id="userSercice" class="cn.zj.spring.service.impl.UserServiceImpl">

<!-- 注入dao -->

<property name="dao" ref="userDao"/>

</bean>

 

 

6.2. 快速生成一個類有多個測試方法的單元測試類

 

 

 

 

 

6.2.1. JDBCTemplate模板類

 

Spring爲各大框架提供對應的模板類能夠直接操做數據庫

 

 

 

若是使用JDBC就使用JDBCTemplate類(將數據庫的基本操做方法已經封裝好了,直接調用便可)

 

導入相關jar

mysql-connector-java-5.x.jar:MySQL驅動包

spring-jdbc-5.0.5.RELEASE.jar:支持JDBC

spring-tx-5.0.5.RELEASE.jar: 支持事務

druid1.9.jar 鏈接池

DAO層代碼

// 引入JDBCTemplate 模板類

private JdbcTemplate jdbcTemplate;

 

//使用setter方式注入數據源便可

public void setDataSource(DataSource dataSource) {

this.jdbcTemplate = new JdbcTemplate(dataSource);

}

 

@Override

public void save(User user) {

this.jdbcTemplate.update("insert into t_user (name,email) values (?,?)",

user.getName(),user.getEmail());

}

 

@Override

public void delete(Integer id) {

this.jdbcTemplate.update("delete from t_user where id = ?",id);

 

}

 

@Override

public void update(User user) {

this.jdbcTemplate.update("update t_user set name = ?,email = ? where id = ?",

user.getName(),user.getEmail(),user.getId());

}

 

@Override

public User findById(Integer id) {

String sql = "select * from t_user where id = ?";

User user = this.jdbcTemplate.queryForObject(sql,new Object[] {id}, new RowMapper<User>() {

@Override

public User mapRow(ResultSet rs, int rowNum) throws SQLException {

User user = new User();

user.setName(rs.getString("name"));

user.setEmail(rs.getString("email"));

user.setId(id);

return user;

}

});

return user;

}

 

@Override

public List<User> list() {

String sql = "select * from t_user";

 

List<User> users = this.jdbcTemplate.query(sql,new RowMapper<User>(){

@Override

public User mapRow(ResultSet rs, int rowNum) throws SQLException {

User user = new User();

user.setName(rs.getString("name"));

user.setEmail(rs.getString("email"));

user.setId(rs.getInt("id"));

return user;

}

});

 

return users;

}

 

 

6.2.2. DAOSupport

問題: 每一個DAO層的實現類都寫上述一樣的代碼,100DAO100,代碼重複99

Spring考慮到這點:專門爲各類持久化操做抽取了 Support父類,開發者本身的到只須要繼承對應的Support類便可

 

public class UserDaoImpl implements UserDao {

// 引入JDBCTemplate 模板類

private JdbcTemplate jdbcTemplate;

 

//使用setter方式注入數據源便可

public void setDataSource(DataSource dataSource) {

this.jdbcTemplate = new JdbcTemplate(dataSource);

}

}

 

JdbcDaoSupport類的結構

public abstract class JdbcDaoSupport extends DaoSupport {

 

@Nullable

private JdbcTemplate jdbcTemplate;

 

 

/**

 * Set the JDBC DataSource to be used by this DAO.

 */

public final void setDataSource(DataSource dataSource) {

if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {

this.jdbcTemplate = createJdbcTemplate(dataSource);

initTemplateConfig();

}

}

@Nullable

public final JdbcTemplate getJdbcTemplate() {

  return this.jdbcTemplate;

}

}

讓本身的類繼承自JdbcDaoSupport類就解決上上述代碼重複問題

public class UserDaoImpl2 extends JdbcDaoSupport implements UserDao {}

 

7. 小結

SpringIOCDI 的配置 可使用XML配置,也能夠註解配置

 

今日內容

註解配置

 

  1. 註解配置IOC (控制反正,將對象的建立權交給Spring-重點

(1) @Component 通用IOC 組件,試用任意Spring對象管理

(2) @Controller 主要在表現層使用

(3) @Service 業務層使用

(4) @Repository DAO層使用

(5) 必須在xml中配置包掃描的位置

(6) <context:component-scan base-package=」cn.zj.spring」>

  1. 註解配置ID (依賴注入)注入對象的屬性(值,集合,引用)-重點

(1) @Autowired + @Qualifier Spring 框架提供

(2) @Resource JavaEE 官方的規範

  1. Spring純註解配置-重點

(1) 純註解配置替代xml配置,可是全部配置依然存在,只是配置方式變換成在類上面貼註解的形式(將來的趨勢)--SpringBoot(純註解)

  1. Spring測試-(理解)

(1) 爲了更方便的開發Spring程序

  1. SpringJDBC-(理解)

(1) 優勢 :主要可以讓Spring自動控制事務

(2) JdbcTemplate 模板類 進行數據表的增刪改查

(3) JdbcDaoSupport

① 優勢: jdbcTemplate模板類的建立進行封裝

② 缺點:只能在xml配置對應DAO

相關文章
相關標籤/搜索