Spring次日筆記java
學習基於註解的IoC配置,你們腦海裏首先得有一個認知,即註解配置和xml配置要實現的功能都是同樣的,都是要下降程序間的耦合。只是配置的形式不同。mysql
關於實際的開發中到底使用xml仍是註解,每家公司有着不一樣的使用習慣。因此這兩種配置方式咱們都須要掌握。web
基於註解配置的方式也已經逐漸代替xml。因此咱們必需要掌握使用註解的方式配置Spring。spring
注意:Eclipse須要先安裝了STS插件,或者使用STS開發工具建立項目。sql
注意:在基於註解的配置中,咱們還要多拷貝一個aop的jar包。以下圖:數據庫
|
|
注意:基於註解整合時,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> |
建立一個測試的服務類,而且加入使用@Component註解,聲明該類容許注入到Spring容器
package com.zj.spring.service;
import org.springframework.stereotype.Component;
//1.使用註解配置,須要將啓動是就建立對象的類表示爲組件類 @Component public class CustomerService {
public void save(){ System.out.println("-保存數據-"); }
}
|
<?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> |
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(); } }
|
--測試結果,若是能夠調用服務方法,測試成功
|
默認狀況下, 被註解@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("-保存數據-"); } } |
咱們將用於被掃描建立對象的註解,統稱爲組件註解。
組件包括:@Component,@Controller,@Service,@Repository。
組件註解的功能都是標識類爲注解的組件類,啓動Spring框架的程序時,聲明將這些組件類注入到Spring容器裏面。意味着,只有加了這四個註解任何一個註解的類,在程序啓動的時候,Spring就經過配置文件指定的路徑將該路徑下的全部帶組件註解的類建立對象而且放在容器裏面。
功能相似原來配置文件的<bean>標籤
問題:明明一個@Component註解就能夠知足了掃描的須要,爲何要有四個呢?
答:其實Spring初版註解的實現(spring 2.5),就是使用一個@Component。從3.0之後,做者認爲根據分層的須要,把它拆成了四個。爲了可讓開發人員,可見便可得,一看到註解,當即知道類的性質。因此分紅了四個
@Controller:用於聲明表示層的組件註解
@Service:用於聲明服務層的組件註解
@Repository:用於聲明持久層的組件註解
@Component:用於聲明三層之外的組件註解
問題:那麼,這四個註解交換使用會報錯嗎。如:持久層,我放@Service標記。
答:處理@Controller在SpringMVC裏面有強制的要求,SpringMVC的表示層必須使用@Controller組件註解。其餘狀況,用亂了是不會報錯的,不過咱們必須不能用亂。不遵照規範,否則別人沒法跟你一塊兒開發了。
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
在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("銷燬方法執行了"); } |
回顧:XML配置文件使用<property name=」」 ref=」」>實現注入的。經過注入註解也能夠實現。
Spring提供了兩套註解能夠解決依對象依賴注入的方案
1,@Autowired +@Qualifier():是Spring定義的標籤
2,@Resouce:是J2EE的規範
@Autowired註解:用於給引用注入容器的對象。
(1) 首先按照依賴對象的類型找,若是找到則使用setter方法或者字段直接注入;
(2) 若是在Spring上下文中找到多個匹配的類型,再按照名字去找,若是沒有匹配則報錯;
(3) 能夠經過使用@Qualifier("otherBean")標籤來規定依賴對象按照bean的id+類型去找
使用@Autowired注入的三種狀況
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(); } }
|
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(); }
}
|
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(); }
}
|
@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(); } } |
@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(); } }
|
除了@Resource註解是Java官方的標準,內置在JDK裏面之外,Spring內置實現的註解聲明放在spring-beans-5.0.5.RELEASE.jar裏面。以下圖所示:
|
<value>
//value只能設置,標量類型=基礎數據類型+包裝類+String
@Value註解:注入基本數據類型以及它們的包裝類和String類型數據的,支持${}注入Properties文件的鍵值對,等同 <proprty name=」...」 value=」${Key}」>。
屬性:
value:注入基本數據類型和String類型數據的
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);
} }
|
//@Component("userDao") @Repository("userDao") public class UserDaoImpl implements UserDao { @Override public void insert(User user) { System.out.println("註冊的Dao方法執行"); } } |
@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; } } |
@Controller public class UserController { /*@Autowired @Qualifier("userService")*/ @Resource(name="userService") private UserService service;
public void register(User user) {
service.register(user); } } |
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); } } |
配置文件(只須要配置一個包掃描便可)
<!-- 配置包掃描 cn.zj.spring : 此包以及子包所有被掃描 --> <context:component-scan base-package="cn.zj.spring"/> |
咱們發現,之因此咱們如今離不開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在初始化容器時要掃描的包。做用和在spring的xml配置文件中的: <context:component-scan base-package="cn.zj.spring"/>是同樣的。 --屬性: basePackages:用於指定要掃描的包。和該註解中的value屬性做用同樣。
|
@PropertySource註解
|
做用: 用於加載.properties文件中的配置。例如咱們配置數據源時,能夠把鏈接數據庫的信息寫到properties配置文件中,就可使用此註解指定properties配置文件的位置。 屬性: value[]:用於指定properties文件位置。若是是在類路徑下,須要寫上classpath:
|
@Bean註解
|
做用: 該註解只能寫在方法上,使用此方法建立一個對象,而且放入spring容器。它就至關於咱們以前在xml配置中介紹的<bean標籤>
屬性: name:給當前@Bean註解方法建立的對象指定一個名稱(即bean的id)。
|
@Import註解
|
做用: 用於導入其餘配置類,在引入其餘配置類時,能夠不用再寫@Configuration註解。固然,寫上也沒問題。 <import > 屬性: value[]:用於指定其餘配置類的字節碼。
|
需求:經過一個簡單的入門示例,實現建立一個配置類使用@Configuration註解和@ComponentScan註解替換xml文件。
建立一個Java項目,導入必須的jar包以及編寫好須要的類結構。代碼目錄以下:
|
--經過該配置類的代碼替換掉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; }
}
|
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); } }
|
--測試結果,輸出組件類調用方法的輸出值。配置成功
|
存在問題:
1,每一個測試都要從新啓動Spring容器,啓動容器的開銷大,測試效率低下。
2,不該該是測試代碼管理Spring容器,應該是Spring容器在管理測試代碼。
|
|
|
Spring測試必須保證Eclipse的單元測試的最低版本是 4.12版本,若是使用的Eclipse版本很低,那麼單元測試版本可能低於4.12,那麼須要開發者手動導入單元測試的jar包
若是使用Spring方式測試,必須使用兩個註解
@RunWith註解
表示先啓動Spring容器,把junit運行在Spring容器中
@ContextConfiguration註解
從哪裏加載資源文件,默認從src(源目錄)下面加載
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(); } }
|
@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(); } } |
Spring對象也支持JDBC,對JDBC只進行了薄薄的一層封裝
問題: Java開發已經有JDBC,爲何Spring還要支持JDBC操做呢?
最重要的緣由: Spring操做JDBC能自動管理事務
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> |
|
|
|
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; }
|
問題: 每一個DAO層的實現類都寫上述一樣的代碼,100個DAO寫100次,代碼重複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 {} |
Spring的IOC和DI 的配置 可使用XML配置,也能夠註解配置
今日內容
註解配置
(1) @Component 通用IOC 組件,試用任意Spring對象管理
(2) @Controller 主要在表現層使用
(3) @Service 業務層使用
(4) @Repository DAO層使用
(5) 必須在xml中配置包掃描的位置
(6) <context:component-scan base-package=」cn.zj.spring」>
(1) @Autowired + @Qualifier Spring 框架提供
(2) @Resource JavaEE 官方的規範
(1) 純註解配置替代xml配置,可是全部配置依然存在,只是配置方式變換成在類上面貼註解的形式(將來的趨勢)--SpringBoot(純註解)
(1) 爲了更方便的開發Spring程序
(1) 優勢 :主要可以讓Spring自動控制事務
(2) JdbcTemplate 模板類 進行數據表的增刪改查
(3) JdbcDaoSupport
① 優勢: 將jdbcTemplate模板類的建立進行封裝
② 缺點:只能在xml配置對應DAO類