摘要:前言在的第二篇中主要講解了模塊的使用容器創建對象的問題,模塊主要是解決對象的創建和對象之間的依賴關系,因此本博文主要講解如何使用容器來解決對象之間的依賴關系回顧以前對象依賴我們來看一下我們以前關于對象依賴,是怎么的歷程直接對象在最開始,我們
前言
在Spring的第二篇中主要講解了Spring Core模塊的使用IOC容器創建對象的問題,Spring Core模塊主要是解決對象的創建和對象之間的依賴關系,因此本博文主要講解如何使用IOC容器來解決對象之間的依賴關系!
回顧以前對象依賴我們來看一下我們以前關于對象依賴,是怎么的歷程
直接new對象在最開始,我們是直接new對象給serice的userDao屬性賦值...
class UserService{ UserDao userDao = new UserDao(); }寫DaoFactory,用字符串來維護依賴關系
后來,我們發現service層緊緊耦合了dao層。我們就寫了DaoFactory,在service層只要通過字符串就能夠創建對應的dao層的對象了。
DaoFactory
public class DaoFactory { private static final DaoFactory factory = new DaoFactory(); private DaoFactory(){} public static DaoFactory getInstance(){ return factory; } publicT createDao(String className,Class clazz){ try{ T t = (T) Class.forName(className).newInstance(); return t; }catch (Exception e) { throw new RuntimeException(e); } } }
serivce
private CategoryDao categoryDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.CategoryDAOImpl", CategoryDao.class); private BookDao bookDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.BookDaoImpl", BookDao.class); private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class); private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);DaoFactory讀取配置文件
再后來,我們發現要修改Dao的實現類,還是得修改service層的源代碼呀..于是我們就在DaoFactory中讀取關于daoImpl的配置文件,根據配置文件來創建對象,這樣一來,創建的是哪個daoImpl對service層就是透明的
DaoFactory
public class DaoFactory { private UserDao userdao = null; private DaoFactory(){ try{ InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties"); Properties prop = new Properties(); prop.load(in); String daoClassName = prop.getProperty("userdao"); userdao = (UserDao)Class.forName(daoClassName).newInstance(); }catch (Exception e) { throw new RuntimeException(e); } } private static final DaoFactory instance = new DaoFactory(); public static DaoFactory getInstance(){ return instance; } public UserDao createUserDao(){ return userdao; } }
service
UserDao dao = DaoFactory.getInstance().createUserDao();Spring依賴注入
通過上面的歷程,我們可以清晰地發現:對象之間的依賴關系,其實就是給對象上的屬性賦值!因為對象上有其他對象的變量,因此存在了依賴...
Spring提供了好幾種的方式來給屬性賦值
1) 通過構造函數
2) 通過set方法給屬性注入值
3) p名稱空間
4)自動裝配(了解)
5) 注解
搭建測試環境UserService中使用userDao變量來維護與Dao層之間的依賴關系
UserAction中使用userService變量來維護與Service層之間的依賴關系
userDao
public class UserDao { public void save() { System.out.println("DB:保存用戶"); } }
userService
public class UserService { private UserDao userDao; public void save() { userDao.save(); } }
userAnction
public class UserAction { private UserService userService; public String execute() { userService.save(); return null; } }構造函數給屬性賦值
其實我們在講解創建帶參數的構造函數的時候已經講過了...我們還是來回顧一下唄..
我們測試service和dao的依賴關系就好了....在serice中加入一個構造函數,參數就是userDao
public UserService(UserDao userDao) { this.userDao = userDao; //看看有沒有拿到userDao System.out.println(userDao); }
applicationContext.xml配置文件
測試:可以成功獲取到userDao對象
// 創建容器對象 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //得到service對象 UserService userService = (UserService) ac.getBean("userService");通過set方法給屬性注入值
我們這里也是測試service和dao層的依賴關系就好了...在service層通過set方法來把userDao注入到UserService中
為UserService添加set方法
public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; //看看有沒有拿到userDao System.out.println(userDao); } public void save() { userDao.save(); } }
applicationContext.xml配置文件:通過property節點來給屬性賦值
引用類型使用ref屬性
基本類型使用value屬性
測試:
內部Bean我們剛才是先創建userDao對象,再由userService對userDao對象進行引用...我們還有另一種思維:先創建userService,發現userService需要userDao的屬性,再創建userDao...我們來看看這種思維方式是怎么配置的:
applicationContext.xml配置文件:property節點內置bean節點
測試
我們發現這種思維方式和服務器訪問的執行順序是一樣的,但是如果userDao要多次被其他service使用的話,就要多次配置了...
p 名稱空間注入屬性值p名稱控件這種方式其實就是set方法的一種優化,優化了配置而已...p名稱空間這個內容需要在Spring3版本以上才能使用...我們來看看:
applicationContext.xml配置文件:使用p名稱空間
測試
自動裝配Spring還提供了自動裝配的功能,能夠非常簡化我們的配置
自動裝載默認是不打開的,自動裝配常用的可分為兩種:
根據名字來裝配
根據類型類裝配
XML配置根據名字applicationContext.xml配置文件:使用自動裝配,根據名字
測試
XML配置根據類型applicationContext.xml配置文件:使用自動裝配,根據類型
值得注意的是:如果使用了根據類型來自動裝配,那么在IOC容器中只能有一個這樣的類型,否則就會報錯!
測試:
我們這只是測試兩個對象之間的依賴關系,如果我們有很多對象,我們也可以使用默認自動分配
使用注解來實現自動裝配@Autowired注解來實現自動裝配:
可以在構造器上修飾
也可以在setter方法上修飾
來自java的@Inject的和@AutoWired有相同的功能
如果沒有匹配到bean,又為了避免異常的出現,我們可以使用required屬性上設置為false。【謹慎對待】
測試代碼
@Component public class UserService { private UserDao userDao ; @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
順利拿到userDao的引用
使用JavaConfig配置類實現對象依賴在
第一種(測試不出來)
import org.springframework.context.annotation.Bean; @org.springframework.context.annotation.Configuration public class Configuration { @Bean() public UserDao userDao() { return new UserDao(); } @Bean public UserService userService() { //直接調用@bean的方法 return new UserService(userDao()); } }
第二種(測試不出來)
import org.springframework.context.annotation.Bean; @org.springframework.context.annotation.Configuration public class Configuration { @Bean() public UserDao userDao() { return new UserDao(); } @Bean public UserService userService(UserDao userDao) { //通過構造函數依賴注入 return new UserService(userDao); } }
如果我直接通過構造器傳入的話,那么報錯了
import org.springframework.beans.factory.annotation.Autowire; import org.springframework.context.annotation.Bean; @org.springframework.context.annotation.Configuration public class Configuration { @Bean() public UserDao userDao() { return new UserDao(); } @Bean(autowire = Autowire.BY_TYPE) public UserService userService(UserDao userDao) { return new UserService(userDao); } }
我測試中只有通過這種方法才能拿到userDao的引用。
public class Configuration { @Bean() public UserDao userDao() { return new UserDao(); } @Bean(autowire = Autowire.BY_TYPE) public UserService userService() { return new UserService(userDao()); } }
當然了,最簡單直觀的方法還有一種:在UserService中加入setUser()方法,那么只要set進去就行了..
UserService
public class UserService { private UserDao userDao ; public UserService() { } public UserService(UserDao userDao) { } public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
Config
import org.springframework.context.annotation.Bean; @org.springframework.context.annotation.Configuration public class Config1 { @Bean(name = "userDao") public UserDao userDao() { return new UserDao(); } @Bean(name="userService") public UserService userService() { UserService userService = new UserService(); userService.setUserDao(userDao()); return userService; } }最后
擴展閱讀:
https://zhuanlan.zhihu.com/p/29426019
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68793.html
摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統一配置,便于修改。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 單例模式你會幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時候花了點時間去學習了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實戰 (第4版)》和《精通Spring4.x 企業應用開發實戰》...
摘要:對象之間耦合度過高的系統,必然會出現牽一發而動全身的情形。控制被反轉之后,獲得依賴對象的過程由自身管理變為了由容器主動注入。于是,他給控制反轉取了一個更合適的名字叫做依賴注入。 Spring還可以這么學--IoC(控制反轉) / DI(依賴注入)理解 聲明:文章的前三部分參考博文:https://www.cnblogs.com/Nouno...這篇文章首發是在我的個人微信訂閱號每天學編...
摘要:入門和學習筆記概述框架的核心有兩個容器作為超級大工廠,負責管理創建所有的對象,這些對象被稱為。中的一些術語切面切面組織多個,放在切面中定義。 Spring入門IOC和AOP學習筆記 概述 Spring框架的核心有兩個: Spring容器作為超級大工廠,負責管理、創建所有的Java對象,這些Java對象被稱為Bean。 Spring容器管理容器中Bean之間的依賴關系,使用一種叫做依賴...
摘要:例如資源的獲取,支持多種消息例如的支持,對多了工具級別的支持等待。最上面的知道吧我就不講了。生命周期事件回調等。他支持不同信息源頭,支持工具類,支持層級容器,支持訪問文件資源,支持事件發布通知,支持接口回調等等。 廣義的 IOC IoC(Inversion of Control) 控制反轉,即不用打電話過來,我們會打給你。 兩種實現: 依賴查找(DL)和依賴注入(DI)。 IOC 和...
摘要:模塊負責的所有面向切面的功能。總結的統一管理,降低了對象之間的耦合對主流的框架提供了很好的集成支持提供眾多組件,事務管理,等具有高度可開放性,開發者可以自由選擇部分或全部主要使用工廠模式和代理模式。 聊完了Spring框架中最重要的兩種設計模式,我們來看一下Spring框架的模塊和結構圖。 Spring框架的結構 下圖是Spring官方給出的Spring框架的結構圖。 showImg(...
閱讀 2181·2021-11-24 10:26
閱讀 2792·2021-11-23 09:51
閱讀 2907·2021-10-08 10:05
閱讀 1683·2021-09-22 15:18
閱讀 1619·2019-08-29 18:45
閱讀 2143·2019-08-29 18:40
閱讀 3332·2019-08-29 16:16
閱讀 2849·2019-08-29 14:21