spring自定义作用域 依赖注入之手动注入
自定義作用域
環境中才支持的request、session、application
到的是同一個bean;單例的bean需要考慮線程安全問題
需要考慮創建bean對性能的影響
我們來看一下這個接口定義
將實現類注冊到spring容器需要調用org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope的方
法,看一下這個方法的聲明
依賴注入之手動注入
通常情況下,系統中類和類之間是有依賴關系的,如果一個類對外提供的功能需要通過調用其他類的方法來實現的時候,說明這兩個類之間存在依賴關系
spring容器內部都提供了支持,這個在spirng中將被依賴的對象設置到依賴的對象中,叫做依賴注入。
spring中依賴注入主要分為手動注入和自動注入,手動注入需要我們明確配置需要注入的對象。
- 通過構造器注入
構造器的參數就是被依賴的對象,構造器注入又分為3種注入方式:
根據構造器參數索引注入
根據構造器參數類型注入
根據構造器參數名稱注入
根據構造器參數索引(位置)注入
用法
UserController userController = new UserController(); userController.setService(userService); //然后就可以使用userController對象了 <bean id="diByConstructorParamIndex" class="com.javacode2018.lesson001.demo5.UserModel"> <constructor-arg index="0" value="xx"/> <constructor-arg index="1" value="上海市"/> </bean>constructor-arg用戶指定構造器的參數
index:構造器參數的位置,從0開始
value:構造器參數的值,value只能用來給簡單的類型設置值,value對應的屬性類型只能為byte,int,long,float,double,boolean,Byte,Long,Float,Double,枚舉,spring容器內部注入的時候會將value的值轉換為對應的類型。
UserModel.java
public class UserModel { private String name; private int age; //描述信息 private String desc; public UserModel() { } public UserModel(String name, String desc) { this.name = name; this.desc = desc; } public UserModel(String name, int age, String desc) { this.name = name; this.age = age; this.desc = desc; } @Override public String toString() { return "UserModel{" + "name='" + name + '\'' + ", age=" + age + ", desc='" + desc + '\'' + '}'; } }diByConstructorParamIndex.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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-4.3.xsd"> <!-- 通過構造器參數的索引注入 --> <bean id="diByConstructorParamIndex" class="com.javacode2018.lesson001.demo5.UserModel"> <constructor-arg index="0" value="路人甲Java"/> <constructor-arg index="1" value="我是通過構造器參數位置注入的"/> </bean> </beans>上面創建UserModel實例代碼相當于下面代碼:
UserModel userModel = new UserModel("路人甲Java","我是通過構造器參數類型注入的");工具類IoUtils.java
import org.springframework.context.support.ClassPathXmlApplicationContext;public class IocUtil { public static ClassPathXmlApplicationContext context(String beanXml) { return new ClassPathXmlApplicationContext(beanXml); } }測試用例DiTest.java
import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 公眾號:路人甲Java,工作10年的前阿里P7分享Java、算法、數據庫方面的技術干貨!堅信用技術改變 命運,讓家人過上更體面的生活! */ public class DiTest { /** * 通過構造器的參數位置注入 */ @Test public void diByConstructorParamIndex() { String beanXml = "classpath:/com/javacode2018/lesson001/demo5/diByConstructorParamIndex.xml"; ClassPathXmlApplicationContext context = IocUtils.context(beanXml); System.out.println(context.getBean("diByConstructorParamIndex")); } }參數位置的注入對參數順序有很強的依賴性,若構造函數參數位置被人調整過,會導致注入出錯。
不過通常情況下,不建議去在代碼中修改構造函數,如果需要新增參數的,可以新增一個構造函數來實現,這算是一種擴展,不會影響目前已有的功能
根據構造器參數類型注入
用法:
<bean id="diByConstructorParamType" class="com.javacode2018.lesson001.demo5.UserModel"> <constructor-arg type="參數類型" value="參數值"/> <constructor-arg type="參數類型" value="參數值"/> </bean>constructor-arg用戶指定構造器的參數
type:構造函數參數的完整類型,如:java.lang.String,int,double
value:構造器參數的值,value只能用來給簡單的類型設置值
案例
diByConstructorParamType.xml
相當于:
UserModel userModel = new UserModel("路人甲Java",30,"我是通過構造器參數類型注入的");新增測試用例
DiTest類中新增一個測試用例
運行diByConstructorParamType輸出
UserModel{name=‘路人甲Java’, age=30, desc=‘我是通過構造器參數類型注入的’}
實際上按照參數位置或者按照參數的類型注入,都有一個問題,很難通過bean的配置文件,知道這個參數是對應UserModel中的那個屬性的,代碼的可讀性不好,比如我想知道這每個參數對應UserModel中的那個屬性,必須要去看UserModel的源碼,下面要介紹按照參數名稱注入的方式比上
面這2種更優秀一些。
根據構造器參數名稱注入
<bean id="diByConstructorParamName" class="com.javacode2018.lesson001.demo5.UserModel"> <constructor-arg name="參數類型" value="參數值"/> <constructor-arg name="參數類型" value="參數值"/> </bean>constructor-arg用戶指定構造器的參數
name:構造參數名稱
value:構造器參數的值,value只能用來給簡單的類型設置值
參數名稱可能不穩定的問題,spring提供了解決方案,通過ConstructorProperties注解來定義參數的名稱,將這個注解加在構造方法上面,如下:
@ConstructorProperties({“第一個參數名稱”, “第二個參數的名稱”,…“第n個參數的名稱”})
public 類名(String p1, String p2…,參數n) {
}
案例
CarModel.java
diByConstructorParamName.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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-4.3.xsd"> <!-- 通過構造器參數的名稱注入 --> <bean id="diByConstructorParamName" class="com.javacode2018.lesson001.demo5.CarModel"> <constructor-arg name="desc" value="我是通過構造器參數類型注入的"/> <constructor-arg name="name" value="保時捷Macans"/> </bean> </beans>相當于:
CarModel carModel = new CarModel("保時捷Macans","我是通過構造器參數類型注入的");增加測試類:
@Test public void diByConstructorParamName() { String beanXml = "classpath:/com/javacode2018/lesson001/demo5/diByConstructorParamName.xml"; ClassPathXmlApplicationContext context = IocUtils.context(beanXml); System.out.println(context.getBean("diByConstructorParamName")); }輸出:
CarModel{name=‘保時捷Macans’, desc=‘我是通過構造器參數類型注入的’}
通常情況下,我們的類都是標準的javabean,javabean類的特點:
屬性都是private訪問級別的
屬性通常情況下通過一組setter(修改器)和getter(訪問器)方法來訪問
setter方法,以set 開頭,后跟首字母大寫的屬性名,如:setUserName,簡單屬性一般只有一個方法參數,方法返回值通常為void;
getter方法,一般屬性以get 開頭,對于boolean類型一般以is 開頭,后跟首字母大寫的屬性名,如:getUserName,isOk;
spring對符合javabean特點類,提供了setter方式的注入,會調用對應屬性的setter方法將被依賴的對象注入進去。
型。
若我們依賴的對象是容器中的其他bean對象的時候,需要用下面的方式進行注入。
注入容器中的bean
注入容器中的bean有兩種寫法:
ref屬性方式
內置bean的方式
- ref屬性方式
將上面介紹的constructor-arg或者property元素的value屬性名稱替換為ref,ref屬性的值為容器中其他bean的名稱,如:
構造器方式,將value替換為ref:
setter方式,將value替換為ref:
<property name="屬性名稱" ref="需要注入的bean的名稱" />- 內置bean的方式
構造器的方式:
setter:
<property name="屬性名稱"> <bean class=""/> </property>案例
PersonModel.java
PersonModel中有依賴于2個對象UserModel、CarModel,下面我們通過spring將UserModel和CarModel創建好,然后注入到PersonModel中,下面創建bean配置文件
diBean.xml
測試類:
@Test public void diBean(){ String beanXml = "classpath:/com/javacode2018/lesson001/demo5/diBean.xml"; ClassPathXmlApplicationContext context = IocUtils.context(beanXml); System.out.println(context.getBean("diBeanByConstructor")); System.out.println(context.getBean("diBeanBySetter")); }出自公眾號路人甲java
總結
以上是生活随笔為你收集整理的spring自定义作用域 依赖注入之手动注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot项目启动后无法访问i
- 下一篇: vue3.x案例 购物车