spring_ioc,DI
什么是IOC呢?
IOC(Inversion of Control),中文意思就是控制反轉(zhuǎn),ioc并不是一種特定的編程語言,指的是一種編程思想,指的是將創(chuàng)建對象的操作權(quán)限交給容器(這里指的是spring容器),通過容器來創(chuàng)建對象和管理對象,簡單來說就是將原先的控制權(quán)由程序本身轉(zhuǎn)給容器(本篇主要指的是spring)
依賴注入依賴注入(Dependency Injection):依賴注入指的是在程序的運行過程中,當(dāng)程序需要調(diào)用另一個對象協(xié)助時,不用在代碼中創(chuàng)建對象并進行調(diào)用,而是將創(chuàng)建過程與調(diào)用過程交給外部的容器來管理(spring),由外部容器創(chuàng)建后傳遞給層序
為什么會有依賴注入的存在?
一個稍微復(fù)雜一點的程序,其組成的類基本都是兩個或兩個以上了,這些類組成應(yīng)用程序完成相關(guān)的業(yè)務(wù)邏輯。每個對象負責(zé)管理與自己相互協(xié)作的對象的引用,一個對象可能會引用多個對象,這就會導(dǎo)致高度的耦合和代碼的難以測試,編碼的基本準則是“低耦合,高內(nèi)聚”
耦合具有兩面性:
1:緊密的耦合會導(dǎo)致代碼難以測試,難以復(fù)用,難以理解
2:一個程序要想完成特定的功能,一定程度的耦合又是必須的,不同的類之間必須進行一定的交互
依賴注入:通過依賴注入,對象的依賴關(guān)系將由負責(zé)協(xié)調(diào)系統(tǒng)中各個對象的第三方組件在創(chuàng)建對象時設(shè)定,對象無需自行創(chuàng)建或管理它們之間的依賴關(guān)系,也就是依賴關(guān)系將被注入到它們的依賴關(guān)系中去
實現(xiàn)依賴注入的兩種方式# 基于xml配置文件的依賴注入
setter方法
以下的例子相當(dāng)于在一個類中使用另一個類中的方法
1:創(chuàng)建一個UserDao接口
package com.doaoao.dao; public interface UserDao {void addUser(); }2:創(chuàng)建UserDao接口的實現(xiàn)類
package com.doaoao.impl; import com.doaoao.dao.UserDao; public class UserDaoImpl implements UserDao {@Overridepublic void addUser() {System.out.println("添加用戶");} }3:創(chuàng)建UserService接口
package com.doaoao.dao; public interface UserService {void addUser(); }4:創(chuàng)建UserService的實現(xiàn)類(在Service中使用UserDao)
package com.doaoao.impl;import com.doaoao.dao.UserDao; import com.doaoao.dao.UserService;public class UserServiceImpl implements UserService {private UserDao userDao;@Overridepublic void addUser() {// 注:之前如果想使用UserDao的對象時,必須先創(chuàng)建該對象,如下 // UserDao userDao = new UserDaoImpl()// 使用spring 由spring為我們創(chuàng)建對象userDao.addUser(); // 調(diào)用UserDaoImpl中的實現(xiàn)方法 }// 要給UserDao添加getter和setter方法public UserDao getUserDao() {return userDao;}// spring容器在實現(xiàn)依賴注入時會調(diào)用set方法,將userDao對象注入給當(dāng)前對象,也就是UserServiceImpl類的對象
public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
5:修改配置文件中的內(nèi)容(當(dāng)Spring讀取配置文件時,會將userDao注入到對應(yīng)的類中)
<bean id="userService" class="com.doaoao.impl.UserServiceImpl"><property name="userDao" ref="userDaoId" /><!-- ref的值為下方bean的id值 userDao與 private UserDao userDao中的userDao命名得一致-->
</bean> <bean id="userDaoId" class="com.doaoao.impl.UserDaoImpl" />
6:添加測試類
@Testpublic void Test02(){// 讀取spring配置文件ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 從配置文件中獲取對應(yīng)id所對應(yīng)的對象UserService userService = (UserService) context.getBean("userService");userService.addUser();}# 使用spring的依賴注入之后,spring容器會幫我們創(chuàng)建UserDaoImpl的對象,并通過setter方法注入到UserService中的userDao屬性上面
## 構(gòu)造注入(容器通過構(gòu)造方法將實例化的對象進行注入)
1:修改之前的UserServiceImpl,添加有參構(gòu)造方法
package com.doaoao.impl; import com.doaoao.dao.UserDao; import com.doaoao.dao.UserService; public class UserServiceImpl implements UserService {private UserDao userDao;@Overridepublic void addUser() {// 注:之前如果想使用UserDao的對象時,必須先創(chuàng)建該對象,如下 // UserDao userDao = new UserDaoImpl()// 使用spring 由spring為我們創(chuàng)建對象userDao.addUser(); // 調(diào)用UserDaoImpl中的實現(xiàn)方法 }// 構(gòu)造注入public UserServiceImpl(UserDao userDao) {this.userDao = userDao;} }?2:修改配置文件
<bean id="userService" class="com.doaoao.impl.UserServiceImpl"><constructor-arg name="userDao" ref="userDaoId" /> </bean> <bean id="userDaoId" class="com.doaoao.impl.UserDaoImpl" /><!-- userDao要與構(gòu)造方法中的參數(shù)一致 UserDao userDao
userDaoId與下方的bean id要一致 -->
?
?
## 基于注解的依賴注入
@Controller -----> springmvc中的controller
@Repository ----> dao層
@Service ---------> service層
@Component --->可以代替上方三個
使用依賴注入,我們九不必再applicationContext.xml中注冊bean
1:在配置文件中添加文件掃描器(使用注解就得先加上文件掃描器,掃描對應(yīng)的類)
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 注冊文件掃描器 --><context:component-scan base-package="com.doaoao" /> </beans>2:在類上使用注解 @Component,該注解中的參數(shù)用于指定該類的id
package com.doaoao.impl; import com.doaoao.dao.UserDao; import org.springframework.stereotype.Repository; @Component("userDao") public class UserDaoImpl implements UserDao {@Overridepublic void addUser() {System.out.println("執(zhí)行了addUser");} }?在spring中提供類與@Component等效的注解
@Repository 用于對 DAO 實現(xiàn)類進行注解
@Service 用于對 Service 實現(xiàn)類進行注解
@Controller 用于對 Controller 實現(xiàn)類進行注解
?例如在dao層的 UserDaoImpl 中使用 @Repository 注解
package com.doaoao.impl; import com.doaoao.dao.UserDao; import org.springframework.stereotype.Repository; @Repository("userDao") public class UserDaoImpl implements UserDao {@Overridepublic void addUser() {System.out.println("執(zhí)行了addUser");} }3:在service層的 UserServiceImpl 上使用 @Service
package com.doaoao.impl; import com.doaoao.dao.UserDao; import com.doaoao.dao.UserService; import org.springframework.stereotype.Service; @Service("userService") public class UserServiceImpl implements UserService {private UserDao userDao;@Overridepublic void addUser() {// 使用spring 由spring為我們創(chuàng)建對象userDao.addUser(); }// 構(gòu)造注入public UserServiceImpl(UserDao userDao) {this.userDao = userDao;} }4:創(chuàng)建測試方法(與之前相同)
@Testpublic void Test02(){// 讀取spring配置文件ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 從配置文件中獲取對應(yīng)id所對應(yīng)的對象UserService userService = (UserService) context.getBean("userService");userService.addUser();}@Autowrite注解
加上該注解后,會按照類型進行裝配,上面的示例中通過UserServiceImpl的構(gòu)造方法對UserDao的注入,我們可以將這個構(gòu)造方法省略,我們可以在private UserDao userDao上添加@Autowired注解,該注解默認使用按類型自動裝配,即容器會查找UserDao類型的實例將其注入,spring容器會自動查找該對象
當(dāng)使用@AUtowrite注解時,@Repository("userDao") 可以改寫成 @Repository,因為默認是根據(jù)類型進行注入的,會自動找到該類型所對應(yīng)的對象
我么可以對其進行修改,讓其根據(jù)名稱進行注入,還可以使用 @Qualifier注解讓@Autowrite根據(jù)名稱自動裝配,
@Qualifier中的名稱要跟UserDaoImpl類中@Repository("userDao")的名稱一致,spring在查找對象時就會根據(jù) userDao這個名字去查找
package com.doaoao.impl;import com.doaoao.dao.UserDao; import com.doaoao.dao.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service;@Service("userService") public class UserServiceImpl implements UserService { @Autowired@Qualifier("userDao")private UserDao userDao;@Overridepublic void addUser() {userDao.addUser(); }// 無需構(gòu)造方法 // public UserServiceImpl(UserDao userDao) { // this.userDao = userDao; // } }@Resource注解(該注解不是spring提供的,是java提供的注解)
該注解默認使用名字進行注解(來完成裝配的/注入的)當(dāng)我們下方?jīng)]有寫名字時,就是使用類型進行裝配的(和 @Autowired)
可以按照名字進行裝配 @Resource(name = “userDao”),當(dāng)指定名字時,名字得和@Repository("userDao") 一樣
@Service("userService") public class UserServiceImpl implements UserService {@Resourceprivate UserDao userDao;@Overridepublic void addUser() {userDao.addUser();} }下面另一種寫法利用類型進行bean的注入
@Service("userService") public class UserServiceImpl implements UserService {@Resource(type = "userDao")private UserDao userDao;@Overridepublic void addUser() {userDao.addUser();} }兩個區(qū)別:@Autowired是spring提供的,@Resource是java提供的,這兩種注解在實際開發(fā)中二選一即可
@Autowired默認根據(jù)類型進行裝配,@Resource默認使用名字進行裝配
?// 使用注解實現(xiàn)初始化和銷毀操作
@PostConstruct public void before() {System.out.println("開始"); }@PreDestroy public void after() {System.out.println("結(jié)束"); }?利用注解@Scope指定bean的作用域,默認的作用域為 singleton 單例模式
@Scope("prototype") @Repository("userDao") public class UserDaoImpl implements UserDao {@Overridepublic void addUser() {System.out.println("執(zhí)行了方法 UserDaoImpl");} }## 注解和xml配置的利弊
注解的好處是,配置方便,直觀。但其弊端也顯而易見:以硬編碼的方式寫入到了 Java代碼中,其修改是需要重新編譯代碼的。
XML 配置方式的最大好處是,對其所做修改,無需編譯代碼,只需重啟服務(wù)器即可將新的配置加載。
若注解與 XML 同用,XML 的優(yōu)先級要高于注解。這樣做的好處是,需要對某個 Bean 做修改,只需修改配置文件即可。當(dāng)然,此時,Bean 類要有 setter 或構(gòu)造器。
## 如何添加多個配置文件
隨著系統(tǒng)中的Bean的數(shù)量增加,會導(dǎo)致配置溫江變得及其的臃腫,會導(dǎo)致可維護性的降低,為了避免這種事情的發(fā)生,可以將Spring配置文件分解成多個配置文件
# 添加多個配置文件-方式1
// 在resource目錄下創(chuàng)建多個配置文件 spring-app.xml spring-bean.xml// 在測試方法中:將配置文件的文件名寫道數(shù)組中,然后將該數(shù)組作為參數(shù)傳入 ClassPathXmlApplicationContex String[] files = {"spring-aop.xml","spring-bean.xml","applicationContext.xml"}; ApplicationContext context = new ClassPathXmlApplicationContext(files);# 添加多個配置文件-方式2
選取一個主配置文件,例如選取 applicationContext.xml
在applicationContext.xml配置文件中加入如下的內(nèi)容,這時就好比將 applicationContext.xml 配置文件變成一個父配置文件
<import resource="spring-aop.xml"/> <import resource="spring-bean.xml"/><!-- 另一種寫法,使用通配符的方式 --><!-- 當(dāng)用通配符的方式寫的時候,主配置文件不以 "spring作為開頭" -->
<import rescorce="spring-*.xml">
?然后再測試代碼中使用即可
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");...
本筆記參考自:小猴子老師教程 http://www.monkey1024.com
轉(zhuǎn)載于:https://www.cnblogs.com/Doaoao/p/10740366.html
總結(jié)
以上是生活随笔為你收集整理的spring_ioc,DI的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈:Wi-Fi 6的优势及应用前景
- 下一篇: [CTSC2010]星际旅行