javascript
06_02_Spring 任务一:IOC控制反转
任務一課程主要內容:
- spring概念介紹
- IOC
- spring快速入門
- spring相關API介紹
- Spring配置文件
- DBUtils
- spring注解開發
- spring整合Junit
一 Spring概述
1.1 Spring是什么
Spring是分層的 Java SE/EE應用 full-stack(全棧式) 輕量級開源框架。
提供了表現層 SpringMVC和持久層 Spring JDBC Template以及 業務層 事務管理等眾多的企業級應用技術,還能整合開源世界眾多著名的第三方框架和類庫,逐漸成為使用最多的Java EE 企業應用開源框架。
兩大核心:以 IOC(Inverse Of Control:控制反轉)和 AOP(Aspect Oriented Programming:面向切面編程)為內核。
IOC:吧對象的創建權交給Spring
AOP:在不修改源代碼的情況下,對方法進行增強
1.2 Spring發展歷程
- EJB
1997 年,IBM提出了EJB 的思想
1998 年,SUN制定開發標準規范 EJB1.0
1999 年,EJB1.1 發布
2001 年,EJB2.0 發布
2003 年,EJB2.1 發布
2006 年,EJB3.0 發布 - Spring
Rod Johnson( Spring 之父)
改變Java世界的大師級人物
2002年編著《Expert one on one J2EE design and development》
指出了JavaEE和EJB組件框架中的存在的一些主要缺陷;提出普通java類依賴注入更為簡單的解決方案。
2004年編著《Expert one-on-one J2EE Development without EJB》闡述了JavaEE開發時不使用EJB的解決方式(Spring 雛形)
同年4月spring1.0誕生
2006年10月,發布 Spring2.0
2009年12月,發布 Spring3.0
2013年12月,發布 Spring4.0
2017年9月, 發布最新 Spring5.0 通用版(GA)
1.3 Spring優勢
- 1)方便解耦,簡化開發
Spring就是一個容器,可以將所有對象創建和關系維護交給Spring管理 什么是耦合度?
對象之間的關系,通常說當一個模塊(對象)更改時也需要更改其他模塊(對象),這就是 耦合,耦合度過高會使代碼的維護成本增加。要盡量解耦. - 2)AOP編程的支持
Spring提供面向切面編程,方便實現程序進行權限攔截,運行監控等功能。 - 3)聲明式事務的支持
通過配置完成事務的管理,無需手動編程 - 4)方便測試
降低JavaEE API的使用 Spring對Junit4支持,可以使用注解測試 - 5)方便集成各種優秀框架
不排除各種優秀的開源框架,內部提供了對各種優秀框架的直接支持
備注:
1.4 Spring體系結構
二 初識IOC
2.1 概述
控制反轉(Inverse Of Control) 不是什么技術,而是一種設計思想。它的目的是指導我們設計出更加松耦合的程序。
控制:在java中指的是對象的控制權限(創建、銷毀)
反轉:指的是對象控制權由原來 由開發者在類中手動控制 反轉到 由Spring容器控制
舉個例子:
- 傳統方式
之前我們需要一個userDao實例,需要開發者自己手動創建 new UserDao(); - IOC方式
現在我們需要一個userDao實例,直接從spring的IOC容器獲得,對象的創建權交給了spring控制
2.2 自定義IOC容器
2.2.1 介紹
需求
實現service層與dao層代碼解耦合
步驟分析
2.2.2 實現
1)創建java項目,導入自定義IOC相關坐標
pom.xml
2)編寫Dao接口和實現類
com.lagou.dao.IUserDao public interface IUserDao {public void seve();}com.lagou.dao.impl.UserDaoImpl public class UserDaoImpl implements IUserDao {public void seve() {System.out.println("dao被調用了,保存成功。。。");}}3)編寫Service接口和實現類
com.lagou.service.IUserService public interface IUserService {public void save(); }com.lagou.service.impl.UserServiceImpl public class UserServiceImpl implements IUserService {public void save() {//調用dao層方法,傳統方式:存在編譯期依賴:耦合重IUserDao userDao = new UserDaoImpl();userDao.seve();} }4)編寫測試代碼
com.lagou.test.SpringTest public class SpringTest {@Testpublic void test1(){//獲取到業務層對象IUserService userService = new UserServiceImpl();//調用save方法userService.save();} }5)問題
當前service對象和dao對象耦合度太高,而且每次new的都是一個新的對象,導致服務器壓力過大。
解耦合的原則是編譯期不依賴,而運行期依賴就行了。
通過反射的方式進行修改,能正常的被調用:
public void save() throws ClassNotFoundException, IllegalAccessException, InstantiationException {//調用dao層方法,傳統方式:存在編譯期依賴:耦合重//IUserDao userDao = new UserDaoImpl();//反射,在反射中會出現硬編碼問題,使用配置文件來解決,//吧全路徑抽取出來,放在一個配置文件中IUserDao userDao =(IUserDao) Class.forName("com.lagou.dao.impl.UserDaoImpl").newInstance();userDao.seve();}改造步驟:
把所有需要創建對象的信息定義在配置文件中
6)編寫beans.xml
把所有需要創建對象的信息定義在配置文件中
beans.xml
7)編寫BeanFactory工具類
com.lagou.utils.BeanFactory
8)修改UserServiceImpl實現類
com.lagou.service.impl.UserServiceImpl
2.2.3 知識小結
其實升級后的BeanFactory就是一個簡單的Spring的IOC容器所具備的功能。
之前我們需要一個userDao實例,需要開發者自己手動創建 new UserDao();
現在我們需要一個userdao實例,直接從spring的IOC容器獲得,對象的創建權交給了spring控制
- 最終目標:代碼解耦合
三 Spring快速入門
3.1 介紹
需求:借助spring的IOC實現service層與dao層代碼解耦合
步驟分析
3.2 實現
1)創建java項目:spring_quickstart,導入spring開發基本坐標
pom.xml
2)編寫Dao接口和實現類
com.lagou.dao.IUserDao public interface IUserDao {public void save(); }com.lagou.dao.impl.UserDaoImpl public class UserDaoImpl implements IUserDao {public void save() {System.out.println("dao被調用了。。。");} }3)創建spring核心配置文件
applicationContext.xml
4)在spring配置文件中配置 UserDaoImpl
applicationContext.xml
5)使用spring相關API獲得Bean實例
com.lagou.test.SpringTest
3.3 知識小結
Spring的開發步驟
四 Spring相關API
4.1 API繼承體系介紹
Spring的API體系異常龐大,我們現在只關注兩個BeanFactory和ApplicationContext,紫色的為接口,中間淺綠色的為中間類,深綠色的為實現類
4.2 BeanFactory
BeanFactory是 IOC 容器的核心接口,它定義了IOC的基本功能。
特點:在第一次調用getBean()方法時,創建指定對象的實例
@Testpublic void test2(){//核心接口,不會創建bean對象存到容器中BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));//getBean的時候才真正的創建bean對象IUserDao userDao =(IUserDao) xmlBeanFactory.getBean("userDao");userDao.save();}4.3 ApplicationContext
代表應用上下文對象,可以獲得spring中IOC容器的Bean對象。
特點:在spring容器啟動時,加載并創建所有對象的實例
常用實現類
它是從類的根路徑下加載配置文件 推薦使用這種。
它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置。
當使用注解配置容器對象時,需要使用此類來創建 spring 容器。它用來讀取注解。
常用方法
根據Bean的id從容器中獲得Bean實例,返回是Object,需要強轉。
根據類型從容器中匹配Bean實例,當容器中相同類型的Bean有多個時,則此方法會報錯。
根據Bean的id和類型獲得Bean實例,解決容器中相同類型Bean有多個情況。
4.4 知識小結
ApplicationContext app = new ClasspathXmlApplicationContext("xml文件"); app.getBean("id"); app.getBean(Class);五 Spring配置文件
5.1 Bean標簽基本配置
<bean id=“” class=“”></bean>
- 用于配置對象交由Spring來創建。
- 基本屬性:
id:Bean實例在Spring容器中的唯一標識
class:Bean的全限定名 - 默認情況下它調用的是類中的 無參構造函數,如果沒有無參構造函數則不能創建成功。
5.2 Bean標簽范圍配置
<bean id="" class="" scope=""></bean>scope屬性指對象的作用范圍(作用域),取值如下:
| singleton | 默認值,單例的 |
| prototype | 多例的 |
| request | WEB項目中,Spring創建一個Bean的對象,將對象存入到request域中 |
| session | WEB項目中,Spring創建一個Bean的對象,將對象存入到session域中 |
| global session | WEB項目中,應用在Portlet環境,如果沒有Portlet環境那么globalSession 相當于 session |
Bean的實例化個數:1個
Bean的實例化時機:當Spring核心文件被加載時,實例化配置的Bean實例
Bean的生命周期:
對象創建:當應用加載,創建容器時,對象就被創建了
對象運行:只要容器在,對象一直活著
對象銷毀:當應用卸載,銷毀容器時,對象就被銷毀了
Bean的實例化個數:多個
Bean的實例化時機:當調用getBean()方法時實例化Bean
Bean的生命周期:
對象創建:當使用對象時,創建新的對象實例
對象運行:只要對象在使用中,就一直活著
對象銷毀:當對象長時間不用時,被 Java 的垃圾回收器回收了
5.3 Bean生命周期配置
<bean id=“” class=“” scope=“” init-method=“” destroy-method=“”></bean>
- init-method:指定類中的初始化方法名稱
- destroy-method:指定類中銷毀方法名稱
5.4 Bean實例化三種方式
- 無參構造方法實例化
- 工廠靜態方法實例化
- 工廠普通方法實例化
5.4.1 無參構造方法實例化
它會根據默認無參構造方法來創建類對象,如果bean中沒有默認無參構造函數,將會創建失敗
<bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>5.4.2 工廠靜態方法實例化
應用場景
依賴的jar包中有個A類,A類中有個靜態方法m1,m1方法的返回值是一個B對象。如果我們頻繁使用B對象,此時我們可以將B對象的創建權交給spring的IOC容器,以后我們在使用B對象時,無需調用A類中的m1方法,直接從IOC容器獲得。
5.4.3 工廠普通方法實例化
應用場景
依賴的jar包中有個A類,A類中有個普通方法m1,m1方法的返回值是一個B對象。如果我們頻繁使用B對象,此時我們可以將B對象的創建權交給spring的IOC容器,以后我們在使用B對象時,無需調用A類中的m1方法,直接從IOC容器獲得.
5.5 Bean依賴注入概述
依賴注入 DI(Dependency Injection):它是 Spring 框架核心 IOC 的具體實現。
在編寫程序時,通過控制反轉,把對象的創建交給了 Spring,但是代碼中不可能出現沒有依賴的情況。IOC 解耦只是降低他們的依賴關系,但不會消除。
例如:業務層仍會調用持久層的方法。
那這種業務層和持久層的依賴關系,在使用 Spring 之后,就讓 Spring 來維護了。簡單的說,就是通過框架把持久層對象傳入業務層,而不用我們自己去獲取。
5.6 Bean依賴注入方式
依賴注入的方式本質上算是兩種:
5.6.1 構造方法
在UserServiceImpl中創建有參構造
com.lagou.service.impl.UserSerivceImpl public class UserSerivceImpl implements IUserService {private IUserDao userDao;//有參構造public UserSerivceImpl(IUserDao userDao) {this.userDao = userDao;}public void save() {//調用dao層的save方法userDao.save();} }創建Service接口
com.lagou.service.IUserService public interface IUserService {public void save(); }配置Spring容器調用有參構造時進行注入
applicationContext.xml<!--方式一:無參構造方法實例化--><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"></bean><!--配置UserService--><bean id="userService" class="com.lagou.service.impl.UserSerivceImpl"> <!-- <constructor-arg index="0" type="com.lagou.dao.IUserDao" ref="userDao"/>--><constructor-arg name="userDao" ref="userDao"/></bean>測試方法:
@Testpublic void test5(){ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");IUserService userService = (IUserService) classPathXmlApplicationContext.getBean("userService");userService.save();}結果:dao被調用了。。。5.6.2 set方法
在UserServiceImpl中創建set方法
public class UserSerivceImpl implements IUserService {private IUserDao userDao;public void setUserDao(IUserDao userDao) {this.userDao = userDao;}public void save() {//調用dao層的save方法userDao.save();} }配置Spring容器調用set方法進行注入
<!--方式一:無參構造方法實例化--><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"></bean><!--配置UserService--><bean id="userService" class="com.lagou.service.impl.UserSerivceImpl"><!--set方法完成依賴注入--><property name="userDao" ref="userDao"/></bean>5.6.3 P命名空間注入
P命名空間注入本質也是set方法注入,但比起上述的set方法注入更加方便,主要體現在配置文件中,如下:
首先,需要引入P命名空間:
其次,需要修改注入方式:
<!--方式一:無參構造方法實例化--><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"></bean><!--配置UserService--><bean id="userService" class="com.lagou.service.impl.UserSerivceImpl" p:userDao-ref="userDao"></bean>5.7 Bean依賴注入的數據類型
上面操作,都是注入Bean對象,除了對象的引用可以注入,普通數據類型和集合都可以在容器中進行注入。
注入數據的三種數據類型
其中引用數據類型,此處就不再贅述了,之前的操作都是對UserDao對象的引用進行注入的。下面將以set方法注入為例,演示普通數據類型和集合數據類型的注入。
5.7.1 注入普通數據類型
public class UserDaoImpl implements IUserDao {//注入普通數據類型private String username;private Integer age;public void setUsername(String username) {this.username = username;}public void setAge(Integer age) {this.age = age;}public void save() {System.out.println(username);System.out.println(age);System.out.println("dao被調用了。。。");} } <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"><!--ref:用于引用數據類型的注入,value是普通數據類型的注入--><property name="username" value="子幕"/><property name="age" value="18"/></bean>5.7.2 注入集合數據類型
1)List集合注入
新建:User類
2)Set集合注入
public class UserDaoImpl implements UserDao {private Set<Object> set;public void setSet(Set<Object> set) {this.set = set;}public void save() {System.out.println(set);System.out.println("保存成功了...");} } <bean id="user" class="com.lagou.domain.User"><property name="username" value="jack"/><property name="age" value="18"/></bean><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"><property name="set"><set><value>bbb</value><ref bean="user"></ref></set></property></bean>3)Array數組注入
public class UserDaoImpl implements UserDao {private Object[] array;public void setArray(Object[] array) {this.array = array;}public void save() {System.out.println(Arrays.toString(array));System.out.println("保存成功了...");} } <bean id="user" class="com.lagou.domain.User"><property name="username" value="jack"/><property name="age" value="18"/></bean><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"><property name="array"><array><value>ccc</value><ref bean="user"></ref></array></property></bean>4)Map集合注入
public class UserDaoImpl implements UserDao {private Map<String, Object> map;public void setMap(Map<String, Object> map) {this.map = map;}public void save() {System.out.println(map);System.out.println("保存成功了...");} } <bean id="user" class="com.lagou.domain.User"><property name="username" value="jack"/><property name="age" value="18"/></bean><bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"><property name="map"><map><entry key="k1" value="ddd"/><entry key="k2" value-ref="user"></entry></map></property></bean>5)Properties配置注入
5.8 配置文件模塊化
實際開發中,Spring的配置內容非常多,這就導致Spring配置很繁雜且體積很大,所以,可以將部分配置拆解到其他配置文件中,也就是所謂的配置文件模塊化。
拆解方式:
按層次進行拆分,例如三層架構
按模塊進行拆分,例如商品模塊
1)并列的多個配置文件
2)主從配置文件(常用)
<beans><import resource="applicationContext-xxx.xml"/> </beans>注意:
- 同一個xml中不能出現相同名稱的bean,如果出現會報錯
- 多個xml如果出現相同名稱的bean,不會報錯,但是后加載的會覆蓋前加載的bean
5.9 知識小結
Spring的重點配置
- <bean>標簽:創建對象并放到spring的IOC容器
id屬性:在容器中Bean實例的唯一標識,不允許重復
class屬性:要實例化的Bean的全限定名
scope屬性:Bean的作用范圍,常用是Singleton(默認)和prototype - <constructor-arg>標簽:屬性注入
name屬性:屬性名稱
value屬性:注入的普通屬性值
ref屬性:注入的對象引用值 - <property>標簽:屬性注入
name屬性:屬性名稱
value屬性:注入的普通屬性值
ref屬性:注入的對象引用值
- <list> <set> <array> <map> <props>
- <import>標簽:導入其他的Spring的配置分文件
六 DbUtils(IOC實戰)
6.1 DbUtils是什么?
DbUtils是Apache的一款用于簡化Dao代碼的工具類,它底層封裝了JDBC技術。
核心對象
核心方法
- int update(); 執行增、刪、改語句
- T query(); 執行查詢語句
ResultSetHandler<T> 這是一個接口,主要作用是將數據庫返回的記錄封裝到實體對象
舉個栗子
查詢數據庫所有賬戶信息到Account實體中
6.2 Spring的xml整合DbUtils
6.2.1 介紹
需求
基于Spring的xml配置實現賬戶的CRUD案例
步驟分析
6.2.2 實現
1)準備數據庫環境
CREATE DATABASE `spring_db`; USE `spring_db`; CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, `money` double DEFAULT NULL, PRIMARY KEY (`id`) ) ; insert into `account`(`id`,`name`,`money`) values (1,'tom',1000), (2,'jerry',1000);2)創建java項目,導入坐標
<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.9</version></dependency><dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.6</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.5.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>3)編寫Account實體類
public class Account {private Integer id;private String name;private Double money;}4)編寫AccountDao接口和實現類
public interface AccountDao {public List<Account> findAll();public Account findById(Integer id);public void save(Account account);public void update(Account account);public void delete(Integer id); } public class AccountDaoImpl implements AccountDao {private QueryRunner queryRunner;public void setQueryRunner(QueryRunner queryRunner) {this.queryRunner = queryRunner;}//查詢所有public List<Account> findAll() {//sqlString sql = "select * from account";List<Account> list = null;try {list = queryRunner.query(sql, new BeanListHandler<Account>(Account.class));} catch (SQLException e) {e.printStackTrace();}return list;}//通過id查詢public Account findById(Integer id) {Account query = null;String sql = "select * from account where id=?";try {query = queryRunner.query(sql, new BeanHandler<Account>(Account.class));} catch (SQLException e) {e.printStackTrace();}return query;}//增加public void save(Account account) {String sql = "INSERT INTO account VALUE(null,?,?)";try {int update = queryRunner.update(sql, account.getName(), account.getMoney());System.out.println("account增加成功");} catch (SQLException e) {e.printStackTrace();}}//修改public void update(Account account) {String sql = "update account set name=?,money=? where id=?";try {int update = queryRunner.update(sql, account.getName(), account.getMoney(), account.getId());System.out.println("Account更新成功");} catch (SQLException e) {e.printStackTrace();}}//通過id進行刪除public void delete(Integer id) {String sql ="delete from account where id=?";try {int update = queryRunner.update(sql, id);} catch (SQLException e) {e.printStackTrace();}} }5)編寫AccountService接口和實現類
public interface AccountService {//查詢所有public List<Account> findAll();//通過id進行查詢public Account findById(Integer id);//添加Accountpublic void save(Account account);//更新Accountpublic void update(Account account);//刪除Accountpublic void delete(Integer id); } public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}public List<Account> findAll() {return accountDao.findAll();}public Account findById(Integer id) {return accountDao.findById(id);}public void save(Account account) {accountDao.save(account);}public void update(Account account) {accountDao.update(account);}public void delete(Integer id) {accountDao.delete(id);} }6)編寫spring核心配置文件
applicationContext.xml
7)編寫測試代碼
public class AccountServiecTest {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");AccountService accountService = (AccountService) classPathXmlApplicationContext.getBean("accountService");//測試添加@Testpublic void testSave(){Account account =new Account();account.setName("lucy");account.setMoney(888d);accountService.save(account);}//測試查詢@Testpublic void testFindById(){Account byId = accountService.findById(3);System.out.println(byId);}//測試查詢所有@Testpublic void testFindAll(){List<Account> all = accountService.findAll();for (Account account : all) {System.out.println(account);}}//測試更新@Testpublic void testUpdate(){Account account = new Account();account.setId(3);account.setName("jack");account.setMoney(999d);accountService.update(account);}//測試更新@Testpublic void testDelete(){accountService.delete(1);} }8)抽取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
6.3 知識小結
- DataSource的創建權交由Spring容器去完成
- QueryRunner的創建權交由Spring容器去完成,使用構造方法傳遞DataSource
- Spring容器加載properties文件
<context:property-placeholder location=“xx.properties”/>
<property name=“” value=“${key}”/>
七 Spring注解開發
Spring是輕代碼而重配置的框架,配置比較繁重,影響開發效率,所以注解開發是一種趨勢,注解代替xml配置文件可以簡化配置,提高開發效率。
7.1 Spring常用注解
7.1.1 介紹
Spring常用注解主要是替代 <bean> 的配置
| @Component | 使用在類上用于實例化Bean |
| @Controller | 使用在web層類上用于實例化Bean |
| @Service | 使用在service層類上用于實例化Bean |
| @Repository | 使用在dao層類上用于實例化Bean |
| @Autowired | 使用在字段上用于根據類型依賴注入 |
| @Qualifier | 結合@Autowired一起使用,根據名稱進行依賴注入 |
| @Resource | 相當于@Autowired+@Qualifier,按照名稱進行注入 |
| @Value | 注入普通屬性 |
| @Scope | 標注Bean的作用范圍 |
| @PostConstruct | 使用在方法上標注該方法是Bean的初始化方法 |
| @PreDestroy | 使用在方法上標注該方法是Bean的銷毀方法 |
說明:
JDK11以后完全移除了javax擴展導致不能使用@resource注解
注意注解開發需要配置組件掃描
使用注解進行開發時,需要在applicationContext.xml中配置組件掃描,作用是指定哪個包及其子包下的Bean需要進行掃描以便識別使用注解配置的類、字段和方法。
<!--注解的組件掃描--> <context:component-scan base-package="com.lagou"></context:component-scan>7.1.2 實現
1)Bean實例化(IOC)
<bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"></bean>使用@Compont或@Repository標識UserDaoImpl需要Spring進行實例化。
// @Component(value = "userDao")@Repository// 如果沒有寫value屬性值,Bean的id為:類名首字母小寫public class UserDaoImpl implements UserDao {}2)屬性依賴注入(DI)
<bean id="userService" class="com.lagou.service.impl.UserServiceImpl"> <property name="userDao" ref="userDaoImpl"/> </bean>使用@Autowired或者@Autowired+@Qulifier或者@Resource進行userDao的注入
@Servicepublic class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;//<property name="userDao" ref="userDaoImpl"/>//@Autowired//@Qualifier("userDaoImpl")//@Resource(name = "userDaoImpl")public void setUserDao(UserDao userDao) {this.userDao = userDao;}}3)@Value
使用@Value進行字符串的注入,結合SPEL表達式獲得配置參數
4)@Scope
<bean scope=""/>使用@Scope標注Bean的范圍
@Service @Scope("singleton") public class UserServiceImpl implements UserService { }5)Bean生命周期
<bean init-method="init" destroy-method="destory" />使用@PostConstruct標注初始化方法,使用@PreDestroy標注銷毀方法
@PostConstruct public void init(){ System.out.println("初始化方法...."); }@PreDestroy public void destroy(){ System.out.println("銷毀方法....."); }7.2 Spring常用注解整合DbUtils
步驟分析
1)拷貝xml配置項目,改為常用注解配置項目
2)修改AccountDaoImpl實現類
@Repository //相當于配置了bean標簽 public class AccountDaoImpl implements AccountDao {@Autowiredprivate QueryRunner queryRunner;... }3)修改AccountServiceImpl實現類
@Service(value = "accountServiceImpl") //相當于配置了bean標簽 value=id屬性 public class AccountServiceImpl implements AccountService {@Autowired //根據類型進行注入 // @Qualifier("accountDao") // @Resource(name = "accountDao")private AccountDao aDao;... }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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd "><!--配置注解掃描--><context:component-scan base-package="com.lagou"></context:component-scan><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!--把數據庫連接池交給IOC容器--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--把QueryRunner交給IOC容器--><bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"><constructor-arg name="ds" ref="dataSource"></constructor-arg></bean> </beans>5)編寫測試代碼
public class AccountServiecTest {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");AccountService accountService = (AccountService) classPathXmlApplicationContext.getBean("accountServiceImpl");//測試查詢所有@Testpublic void testFindAll() {List<Account> all = accountService.findAll();for (Account account : all) {System.out.println(account);} // classPathXmlApplicationContext.close();} }7.3 Spring新注解
使用上面的注解還不能全部替代xml配置文件,還需要使用注解替代的配置如下:
- 非自定義的Bean的配置:<bean>
- 加載properties文件的配置:<context:property-placeholder>
- 組件掃描的配置:<context:component-scan>
- 引入其他文件:<import>
| @Configuration | 用于指定當前類是一個Spring 配置類,當創建容器時會從該類上加載注解 |
| @Bean | 使用在方法上,標注將該方法的返回值存儲到 Spring 容器中 |
| @PropertySource | 用于加載 properties 文件中的配置 |
| @ComponentScan | 用于指定 Spring 在初始化容器時要掃描的包 |
| @Import | 用于導入其他配置類 |
7.4 Spring純注解整合DbUtils
步驟分析
1)編寫Spring核心配置類
com.lagou.config.SpringConfig/* * 配置文件 * */ @Configuration @ComponentScan("com.lagou") @Import(DataSourceConfig.class) public class SpringConfig {@Beanpublic QueryRunner getQueryRunner(@Autowired DataSource dataSource){QueryRunner queryRunner = new QueryRunner(dataSource);return queryRunner;} }2)編寫數據庫配置信息類
com.lagou.config.DataSourceConfig@PropertySource("classpath:jdbc.properties") public class DataSourceConfig {@Value("${jdbc.driverClassName}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Bean("dataSource") //會將當前的返回值放到IOC容器中,如果不起名字那么在IOC中key的值會是方法的名字public DataSource getDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName(driver);druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return druidDataSource;} }3)編寫測試代碼
public class AccountServiceTest {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); AccountService accountService = applicationContext.getBean(AccountService.class); //AccountService accountService = applicationContext.getBean("accountServiceImpl");//測試查詢@Testpublic void testFindById() {Account account = accountService.findById(3); System.out.println(account);}}八 Spring整合Junit
8.1普通Junit測試問題
在普通的測試類中,需要開發者手動加載配置文件并創建Spring容器,然后通過Spring相關API獲得Bean實例;如果不這么做,那么無法從容器中獲得對象。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountService accountService = applicationContext.getBean(AccountService.class);我們可以讓SpringJunit負責創建Spring容器來簡化這個操作,開發者可以直接在測試類注入Bean實例;但是需要將配置文件的名稱告訴它。
8.2 Spring整合Junit
步驟分析
1)導入spring集成Junit的坐標
pom.xml
2)使用@Runwith注解替換原來的運行器
@RunWhth指定junit的運行環境 SpringJUnit4ClassRunner是spring提供的作為junit運行環境的一個類
3)使用@ContextConfiguration指定配置文件或配置類
@RunWith(SpringJUnit4ClassRunner.class)//@RunWhth指定junit的運行環境 SpringJUnit4ClassRunner是spring提供的作為junit運行環境的一個類 //@ContextConfiguration(value = {"classpath:applicationContext.xml"}) 加載spring 核心配置文件 @ContextConfiguration(classes = {SpringConfig.class}) // 加載spring核心配置類 public class SpringJunitTest { }4)使用@Autowired注入需要測試的對象
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringConfig.class}) public class SpringJunitTest { @Autowired private AccountService accountService; }5)創建測試方法進行測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringConfig.class}) public class SpringJunitTest {@Autowired private AccountService accountService; //測試查詢所有@Testpublic void testFindAll() {List<Account> all = accountService.findAll();for (Account account : all) {System.out.println(account);}} }總結
以上是生活随笔為你收集整理的06_02_Spring 任务一:IOC控制反转的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度网盘下载软件(10+m)
- 下一篇: 分切机设备的全球与中国市场2022-20