Spring第三篇【Core模塊之對象依賴】


tags: Spring


前言

在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;}public <T> T createDao(String className,Class<T> 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方法給屬性注入值
    1. 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;//看看有沒有拿到userDaoSystem.out.println(userDao);}復制代碼

applicationContext.xml配置文件

<!--創建userDao對象--><bean id="userDao" class="UserDao"/><!--創建userService對象--><bean id="userService" class="UserService"><!--要想在userService層中能夠引用到userDao,就必須先創建userDao對象--><constructor-arg index="0" name="userDao" type="UserDao" ref="userDao"></constructor-arg></bean>復制代碼
  • 測試:可以成功獲取到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;//看看有沒有拿到userDaoSystem.out.println(userDao);}public void save() {userDao.save();}
}復制代碼

applicationContext.xml配置文件:通過property節點來給屬性賦值

  • 引用類型使用ref屬性
  • 基本類型使用value屬性
<!--創建userDao對象--><bean id="userDao" class="UserDao"/><!--創建userService對象--><bean id="userService" class="UserService"><property name="userDao" ref="userDao"/></bean>復制代碼
  • 測試:


內部Bean

我們剛才是先創建userDao對象,再由userService對userDao對象進行引用...我們還有另一種思維:先創建userService,發現userService需要userDao的屬性,再創建userDao...我們來看看這種思維方式是怎么配置的:

applicationContext.xml配置文件:property節點內置bean節點

<!--1.創建userService,看到有userDao這個屬性2.而userDao這個屬性又是一個對象3.在property屬性下又內置了一個bean4.創建userDao--><bean id="userService" class="UserService"><property name="userDao"><bean id="userDao" class="UserDao"/></property></bean>復制代碼
  • 測試

我們發現這種思維方式和服務器訪問的執行順序是一樣的,但是如果userDao要多次被其他service使用的話,就要多次配置了...

p 名稱空間注入屬性值

p名稱控件這種方式其實就是set方法的一種優化,優化了配置而已...p名稱空間這個內容需要在Spring3版本以上才能使用...我們來看看:

applicationContext.xml配置文件:使用p名稱空間

<bean id="userDao" class="UserDao"/><!--不用寫property節點了,直接使用p名稱空間--><bean id="userService" class="UserService" p:userDao-ref="userDao"/>復制代碼
  • 測試


自動裝配

Spring還提供了自動裝配的功能,能夠非常簡化我們的配置

自動裝載默認是不打開的,自動裝配常用的可分為兩種:

  • 根據名字來裝配
  • 根據類型類裝配

XML配置根據名字

applicationContext.xml配置文件:使用自動裝配,根據名字

<bean id="userDao" class="UserDao"/><!--1.通過名字來自動裝配2.發現userService中有個叫userDao的屬性3.看看IOC容器中沒有叫userDao的對象4.如果有,就裝配進去--><bean id="userService" class="UserService" autowire="byName"/>復制代碼
  • 測試


XML配置根據類型

applicationContext.xml配置文件:使用自動裝配,根據類型

值得注意的是:如果使用了根據類型來自動裝配,那么在IOC容器中只能有一個這樣的類型,否則就會報錯!

<bean id="userDao" class="UserDao"/><!--1.通過名字來自動裝配2.發現userService中有個叫userDao的屬性3.看看IOC容器UserDao類型的對象4.如果有,就裝配進去--><bean id="userService" class="UserService" autowire="byType"/>復制代碼
  • 測試:


我們這只是測試兩個對象之間的依賴關系,如果我們有很多對象,我們也可以使用默認自動分配


###使用注解來實現自動裝配###

@Autowired注解來實現自動裝配:

  • 可以在構造器上修飾
  • 也可以在setter方法上修飾
  • 來自java的@Inject的和@AutoWired有相同的功能

如果沒有匹配到bean,又為了避免異常的出現,我們可以使用required屬性上設置為false。【謹慎對待】

  • 測試代碼
@Component
public class UserService {private UserDao userDao ;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
復制代碼

順利拿到userDao的引用

注解

自從jdk5有了注解這個新特性,我們可以看到Struts2框架、Hibernate框架都支持使用注解來配置信息...

通過注解來配置信息就是為了簡化IOC容器的配置,注解可以把對象添加到IOC容器中、處理對象依賴關系,我們來看看怎么用吧:

使用注解步驟:

  • 1)先引入context名稱空間
    •   xmlns:context="http://www.springframework.org/schema/context"
      復制代碼
  • 2)開啟注解掃描器
    •   `<context:component-scan base-package=""></context:component-scan>`
      復制代碼
    • 第二種方法:也可以通過自定義掃描類以@CompoentScan修飾來掃描IOC容器的bean對象。。如下代碼:

//表明該類是配置類
@Configuration//啟動掃描器,掃描bb包下的//也可以指定多個基礎包//也可以指定類型
@ComponentScan("bb")
public class AnnotationScan {}
復制代碼

在使用@ComponentScan()這個注解的時候,在測試類上需要@ContextConfiguration這個注解來加載配置類...

  • @ContextConfiguration這個注解又在Spring的test包下..

創建對象以及處理對象依賴關系,相關的注解:

  • @ComponentScan掃描器
  • @Configuration表明該類是配置類
  • @Component 指定把一個對象加入IOC容器--->@Name也可以實現相同的效果【一般少用】
  • @Repository 作用同@Component; 在持久層使用
  • @Service 作用同@Component; 在業務邏輯層使用
  • @Controller 作用同@Component; 在控制層使用
  • @Resource 依賴關系
    • 如果@Resource不指定值,那么就根據類型來找,相同的類型在IOC容器中不能有兩個
    • 如果@Resource指定了值,那么就根據名字來找

測試代碼

  • UserDao
package aa;import org.springframework.stereotype.Repository;/*** Created by ozc on 2017/5/10.*///把對象添加到容器中,首字母會小寫
@Repository
public class UserDao {public void save() {System.out.println("DB:保存用戶");}}復制代碼
  • userService

package aa;import org.springframework.stereotype.Service;import javax.annotation.Resource;//把UserService對象添加到IOC容器中,首字母會小寫
@Service
public class UserService {//如果@Resource不指定值,那么就根據類型來找--->UserDao....當然了,IOC容器不能有兩個UserDao類型的對象//@Resource//如果指定了值,那么Spring就在IOC容器找有沒有id為userDao的對象。@Resource(name = "userDao")private UserDao userDao;public void save() {userDao.save();}
}復制代碼
  • userAction

package aa;import org.springframework.stereotype.Controller;import javax.annotation.Resource;/*** Created by ozc on 2017/5/10.*///把對象添加到IOC容器中,首字母會小寫
@Controller
public class UserAction {@Resource(name = "userService")private UserService userService;public String execute() {userService.save();return null;}
}復制代碼
  • 測試

package aa;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** Created by ozc on 2017/5/10.*/
public class App {public static void main(String[] args) {// 創建容器對象ApplicationContext ac = new ClassPathXmlApplicationContext("aa/applicationContext.xml");UserAction userAction = (UserAction) ac.getBean("userAction");userAction.execute();}
}復制代碼

注解和XML配置是可以混合使用的...


如果您覺得這篇文章幫助到了您,可以給作者一點鼓勵

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539592.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539592.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539592.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spring框架結構介紹

Spring提供了一站式解決方案&#xff1a; 1&#xff09; Spring Core spring的核心功能&#xff1a; IOC容器, 解決對象創建及依賴關系 2&#xff09; Spring Web Spring對web模塊的支持。 -->可以與struts整合,讓struts的action創建交給spring -->spring mvc模式 3…

java通過J2C獲取用戶名密碼_WAS服務器上的J2C別名有什么用途?

這是我LdapTemplate類 公共LdapTemplate getLdapTemplete(字符串ldapID) {WAS服務器上的J2C別名有什么用途&#xff1f;if (ldapID.equalsIgnoreCase(Constants.LDAP1)){if (ldapTemplate1 null){try{PasswordCredential passwordCredential j2cAliasUtility.getAliasDetails…

百度坐標轉換API使用

http://api.map.baidu.com/geoconv/v1/?coords121.54759,29.870724&from1&to5&aksGSOaO07WkRHHiCRxxbSQVBn 前提&#xff1a;121.54759,29.870724 是由手機硬件或谷歌地圖獲取的 錯誤的方法一&#xff1a; function standard2china(lng,lat){//http://api.map.ba…

Java語言所有異常類均繼承自_Java將運行錯誤分為兩類:(__)和(__), 其對應的類均派生自(__)類;...

【單選題】設 x,y 均為已定義的類名,下列聲明對象x1的語句中正確的是( )【判斷題】構造函數的方法名可以由編程人員任意命名。【單選題】能夠實現對原文的鑒別和不可否認性的認證技術是( )。【單選題】設有定義語句int a[]{66,88,99}; 則以下對此語句的敘述錯誤的是( )。【判斷…

Quartz業務類無法注入Spring對象問題

tags: 解決錯誤, titile: Quartz業務類無法注入Spring對象問題 Quartz業務類無法注入Spring對象問題 在剛開始遇到的時候還以為是Spring配置哪里錯誤了&#xff0c;結果搞了那么久&#xff0c;才知道Quartz與Spring注入對象是不關聯的。。 因為Quartz的業務Job對象是由Quartz來…

如何解決ajax跨域問題

原文&#xff1a;http://www.congmo.net/blog/2012/06/27/ajax-cross-domain/ 跨域問題 起 因是這樣的&#xff0c;為了復用&#xff0c;減少重復開發&#xff0c;單獨開發了一個用戶權限管理系統&#xff0c;共其他系統獲取認證與授權信息&#xff0c;暫且稱之為A系統&#xf…

spring bean創建細節

1) 對象創建&#xff1a; 單例/多例 scope"singleton", 默認值&#xff0c;即默認是單例【service/dao/工具類】 scope"prototype", 多例&#xff1b;【Action對象】 2) 什么時候創建? scope"prototype" 在用到對象的時候&#xff0c…

發送郵件程序報錯454 Authentication failed以及POP3和SMTP簡介

一、發現問題 在測試郵件發送程序的時候&#xff0c;發送給自己的QQ郵箱&#xff0c;程序報錯454 Authentication failed, please open smtp flag first。 二、解決問題 進入QQ郵箱——>設置——>賬戶——>POP3/IMAP/SMTP選擇——>開啟POP3/SMTP服務。 三、POP3和S…

MySQL數據庫是非關系_MySQL(數據庫)基礎知識、關系型數據庫yu非關系型數據庫、連接認證...

什么是數據庫&#xff1f;數據庫(Database)&#xff1a;存儲數據的倉庫高效地存儲和處理數據的介質(介質主要是兩種&#xff1a;磁盤和內存)數據庫系統&#xff1a;DBS(Database System)&#xff1a;是一種虛擬系統&#xff0c;將多種內容關聯起來的稱呼DBS DBMS DBDBMS&…

WPF 使用MahApps.Metro UI庫

http://www.cnblogs.com/happyyftk/p/6904766.html 本文示例源碼下載&#xff1a;MetroWPF 官方示例地址&#xff1a;http://mahapps.com/guides/quick-start.html 官方控件示例地址&#xff1a;http://mahapps.com/controls/ MahApps.Metro 項目源碼&#xff1a;https://githu…

SpringIOC容器-創建對象

SpringIOC容器&#xff0c;是spring核心內容。功能&#xff1a;創建對象&#xff0c;處理對象的依賴關系 IOC容器創建對象&#xff1a; 創建對象, 有幾種方式&#xff1a; 1&#xff09; 調用無參數構造器 2&#xff09; 帶參數構造器 3&#xff09; 工廠創建對象 工廠類&…

java注釋搞笑圖案_搞笑的代碼注釋,那些有趣的程序員

發表于 2019-04-24 16:11:26 by 月小升搞笑/**** .::::.* .::::::::.* ::::::::::: F*CK YOU* ..:::::::::::* ::::::::::::* .::::::::::* ::::::::::::::..* ..::::::::::::.* ::::::::::::::::* ::::::::::::: .:::.* :::: ::::: .::::::::.* .:::: :::: .:::::::::::.* .::…

SpringIOC容器-對象依賴

1 概述 Spring中&#xff0c;如何給對象的屬性賦值? 【DI, 依賴注入】 1) 通過構造函數 2) 通過set方法給屬性注入值 3) p名稱空間 4) 自動裝配 5) 注解 1.1 通過構造函數 <!-- ###############對象屬性賦值############### --><!-- 1) 通過構造函數 --><be…

f5長連接策略

但是把這些短連接匯聚到一起&#xff0c;集中F5的設備上&#xff0c;通過F5與服務器建立平滑的長連接&#xff0c;就解決了不斷增大的并發連接。比如說前臺有15萬個并發連接&#xff0c;經過F5的優化&#xff0c;在服務器上只有不到5000個并發連接&#xff0c;而且在此過程中&a…

pdo-mysql_PHP: MySQL (PDO) - Manual

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY(int)Если этот атрибут установлен в true вPDOStatement, MySQL-драйвербудет использовать буферизованные версии API MySQL.Если вы пишете пе…

Spring IOC容器【p名稱空間注入屬性值 】

# p 名稱空間給對象的屬性注入值(spring3.0以上版本才支持) 需要引入&#xff1a; xmlns:p"http://www.springframework.org/schema/p" 舉例 applicationContext.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http…

Spring properties定義bean

2019獨角獸企業重金招聘Python工程師標準>>> Spring提供了豐富的標簽和注解來進行bean的定義&#xff0c;除此之外框架來提供了擴展機制讓使用可以通過properties來定義bean&#xff0c;與強大的標簽式和注解式的bean定義相比&#xff0c;properties提供的規則要簡單…

Spring IOC容器-自動裝配

1 autowire"byName" 根據名稱自動裝配&#xff0c;自動去IOC容器中找與屬性名同名的引用的對象&#xff0c;并自動注入。 <!-- ###############自動裝配############### --> <bean id"userDao" class"d_auto.UserDao"></bean&g…

linux下C++遍歷文件夾下的全部文件;Windows/Linux下C++批量修改文件名,批量刪除文件...

Linux下 C遍歷目錄下所有文件 1 rename(image_path.c_str(), image_path_new.c_str()); 2 remove(image_path_move.c_str()); 上述批量操作的代碼是在linux下的參數設置&#xff1a; rename的參數&#xff0c;image_path為原文件的路徑文件名&#xff0c;image_path_new為文件…

mongodb java 單例_Java單例MongoDB工具類

我經常對MongoDB進行一些基礎操作&#xff0c;將這些常用操作合并到一個工具類中&#xff0c;方便自己開發使用。沒用Spring Data、Morphia等框架是為了減少學習、維護成本&#xff0c;另外自己直接JDBC方式的話可以更靈活&#xff0c;為自己以后的積累留一個腳印。Java驅動版本…