1、依賴注入的三種方式
在實際環境中實現IoC容器的方式主要分爲兩大類,一類是依賴查找,依賴查找是經過資源定位,把對應的資源查找回來。另外一類則是依賴注入。
通常而言,依賴注入可分爲3中方式:html
構造器注入和setter注入是主要的注入方式,而接口注入是從別的地方注入的方式,好比,在Web工程中,配置的數據源每每是經過服務器(好比tomcat)
去配置的,這個時候能夠用JNDI(Java Naming and Directory interface)的形式經過接口將它注入Spring IoC容器中來,下面就是對它們進行詳解。
一、構造器注入
構造器注入依賴於構造方法實現,而構造方法是能夠是有參構造或無參構造。在大部分狀況下,咱們都是經過類的構造方法來建立類的對象,Spring也能夠採用反射的方式,
經過使用構造方法完成注入,這就是構造器注入的原理。
爲了讓Spring完成對應的構造注入,咱們由必要取描述具體的類,構造方法並設置對應的參數,這樣Spring就會經過對應的信息用反射的形式建立對象。
二、使用setter注入
setter注入是Spring中最主流的注入方式,它利用Java Bean規範所定義的setter方法來完成注入,靈活且可讀性高。它消除了使用構造器注入時出現多個參數的可能性,
首先能夠把構造方法聲明爲無參構造,而後使用setter注入爲其設置對應的值,其實也是經過Java反射技術得以實現的。java
三、接口注入
有時候資源並非來至自身系統,而是來至外界,好比數據庫鏈接資源徹底能夠在tomcat下配置,單後經過JNDI的形式去獲取它,這樣數據庫鏈接資源是屬於開發工程外的資源,這個時候咱們
能夠採用接口注入的形式來獲取它,好比在tomcat中能夠配置參數數據源,又如在Eclipse中配置了tomcat後,能夠打開服務器的context.xml文件。
2、三種注入方式的測試案例spring
總的配置文件:applicationContext.xmlsql
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 7 <!-- 依賴注入·構造器注入 --> 8 <bean id="user_xfwl" class="com.xfwl.spring.DI.UserBean"> 9 <constructor-arg index="0" value="小風微涼"/> 10 <constructor-arg index="1" value="123456"/> 11 </bean> 12 <!-- 依賴注入·setter注入 --> 13 <bean id="admin_xfwl" class="com.xfwl.spring.DI.Administrators"> 14 <property name="aid" value="100001"></property> 15 <property name="aname" value="小風微涼"></property> 16 <property name="apwd" value="123456"></property> 17 </bean> 18 <bean id="dao" class="com.xfwl.spring.DI.DAO"> 19 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 20 <property name="url" value="jdbc:oracle:thin:@***.36.17.**:1521:***"/> 21 <property name="username" value="***"/> 22 <property name="password" value="***"/> 23 </bean> 24 <bean id="daoImpl" class="com.xfwl.spring.DI.LoginDaoImp"> 25 <property name="dao" ref="dao"/> 26 </bean> 27 28 <!-- 依賴注入·接口注入 --> 29 <!-- 配置數據源,使用C3P0鏈接池 的接口注入實現--> 30 <bean name="dataSource" 31 class="com.mchange.v2.c3p0.ComboPooledDataSource"> 32 <property name="driverClass" value="${jdbc.driverClass}"></property> 33 <property name="jdbcUrl" value="${jdbc.url}"></property> 34 <property name="user" value="${jdbc.username}"></property> 35 <property name="password" value="${jdbc.password}"></property> 36 <!-- 指定鏈接池中保留的[最大鏈接數]. Default:15--> 37 <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/> 38 <!-- 指定鏈接池中保留的[最小鏈接數]--> 39 <property name="minPoolSize" value="${jdbc.minPoolSize}"/> 40 <!-- 指定鏈接池的初[始化鏈接數] 取值應在minPoolSize 與 maxPoolSize 之間.Default:3--> 41 <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/> 42 <!-- [最大空閒時間],60秒內未使用則鏈接被丟棄。若爲0則永不丟棄。 Default:0--> 43 <property name="maxIdleTime" value="${jdbc.maxIdleTime}"/> 44 <!-- 當鏈接池中的鏈接耗盡的時候c3p0[一次同時獲取的鏈接數]. Default:3--> 45 <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/> 46 <!-- 47 JDBC的標準,用以控制數據源內加載的PreparedStatements數量。 48 但因爲預緩存的statements屬於單個connection而不是整個鏈接池因此設置這個參數須要考慮到多方面的因數. 49 若是maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default:0 50 --> 51 <property name="maxStatements" value="${jdbc.maxStatements}"/> 52 <!-- 每60秒檢查全部鏈接池中的[空閒鏈接].Default:0 --> 53 <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/> 54 </bean> 55 </beans>
一、構造器注入數據庫
1 package com.xfwl.spring.DI; 2 /** 3 * 測試依賴注入-構造器注入 4 * @function 5 * @author 小風微涼 6 * @time 2018-7-10 下午2:17:16 7 */ 8 public class UserBean { 9 private String uname; 10 private String upwd; 11 //無參構造 12 public UserBean(){} 13 //有參構造 14 public UserBean(String uname,String upwd){ 15 this.uname=uname; 16 this.upwd=upwd; 17 } 18 public String getUname() { 19 return uname; 20 } 21 public void setUname(String uname) { 22 this.uname = uname; 23 } 24 public String getUpwd() { 25 return upwd; 26 } 27 public void setUpwd(String upwd) { 28 this.upwd = upwd; 29 } 30 @Override 31 public String toString() { 32 return "UserBean [uname=" + uname + ", upwd=" + upwd + "]"; 33 } 34 }
配置文件:apache
1 <!-- 依賴注入·構造器注入 --> 2 <bean id="user_xfwl" class="com.xfwl.spring.DI.UserBean"> 3 <constructor-arg index="0" value="小風微涼"/> 4 <constructor-arg index="1" value="123456"/> 5 </bean>
二、使用setter注入緩存
1 package com.xfwl.spring.DI; 2 /** 3 * 依賴注入·setter注入 4 * @function 5 * @author 小風微涼 6 * @time 2018-7-10 下午2:37:54 7 */ 8 public class Administrators { 9 private String aid; 10 private String aname; 11 private String apwd; 12 13 public Administrators(){} 14 15 public String getAid() { 16 return aid; 17 } 18 19 public void setAid(String aid) { 20 this.aid = aid; 21 } 22 23 public String getAname() { 24 return aname; 25 } 26 27 public void setAname(String aname) { 28 this.aname = aname; 29 } 30 31 public String getApwd() { 32 return apwd; 33 } 34 35 public void setApwd(String apwd) { 36 this.apwd = apwd; 37 } 38 39 @Override 40 public String toString() { 41 return "Administrators [aid=" + aid + ", aname=" + aname + ", apwd=" 42 + apwd + "]"; 43 } 44 45 }
測試使用setter注入鏈接數據庫,實現一次查詢tomcat
建立一個DAO.java服務器
1 package com.xfwl.spring.DI; 2 3 import java.sql.Connection; 4 import java.sql.Driver; 5 import java.sql.DriverManager; 6 import java.sql.SQLException; 7 8 /** 9 * 登陸鏈接DAO 10 * @function 11 * @author 小風微涼 12 * @time 2018-7-10 下午3:21:43 13 */ 14 public class DAO { 15 private String driverClassName; 16 private String url; 17 private String username; 18 private String password; 19 /** 20 * 獲取數據庫鏈接 21 * @param driverClassName 22 */ 23 public Connection getConn(){ 24 Connection con=null; 25 try{ 26 //加載Oracle的驅動類 27 Class.forName(driverClassName) ; 28 con =DriverManager.getConnection(url , username , password ) ; 29 }catch(SQLException ex){ 30 System.out.println("數據庫鏈接失敗!"); 31 ex.printStackTrace() ; 32 } catch (ClassNotFoundException e) { 33 34 System.out.println("數據庫鏈接失敗!"); 35 e.printStackTrace() ; 36 } 37 return con; 38 } 39 /** 40 * 釋放數據庫鏈接 41 * @param driverClassName 42 */ 43 public void releaseConn(Connection conn){ 44 try { 45 if(!conn.isClosed()){ 46 conn.close(); 47 } 48 } catch (SQLException e) { 49 e.printStackTrace(); 50 } 51 } 52 public void setDriverClassName(String driverClassName) { 53 this.driverClassName = driverClassName; 54 } 55 public void setUrl(String url) { 56 this.url = url; 57 } 58 public void setUsername(String username) { 59 this.username = username; 60 } 61 public void setPassword(String password) { 62 this.password = password; 63 } 64 }
建立一個LoginDaoImp.java多線程
1 package com.xfwl.spring.DI; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 /** 9 * 登陸DAO 10 * @function 11 * @author 小風微涼 12 * @time 2018-7-10 下午3:21:43 13 */ 14 public class LoginDaoImp { 15 private DAO dao; 16 public void queryCstListByNo(String cstNo) throws SQLException{ 17 Connection conn=dao.getConn(); 18 String sql="SELECT CIF_CSTNO,CIF_HOSTNO,CIF_NAMECN FROM CB_CST_INF WHERE CIF_CSTNO=?"; 19 PreparedStatement pst=conn.prepareStatement(sql); 20 pst.setString(1, cstNo); 21 ResultSet result=pst.executeQuery(); 22 while(result.next()){ 23 System.out.println("企業客戶號:"+result.getString("CIF_CSTNO")); 24 System.out.println("核心客戶號:"+result.getString("CIF_HOSTNO")); 25 System.out.println("客戶名稱:"+result.getString("CIF_HOSTNO")); 26 } 27 dao.releaseConn(conn); 28 } 29 public DAO getDao() { 30 return dao; 31 } 32 public void setDao(DAO dao) { 33 this.dao = dao; 34 } 35 }
配置文件:
1 <!-- 依賴注入·setter注入 --> 2 <bean id="admin_xfwl" class="com.xfwl.spring.DI.Administrators"> 3 <property name="aid" value="100001"></property> 4 <property name="aname" value="小風微涼"></property> 5 <property name="apwd" value="123456"></property> 6 </bean> 7 <bean id="dao" class="com.xfwl.spring.DI.DAO"> 8 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 9 <property name="url" value="jdbc:oracle:thin:@***.36.17.**:1521:***"/> 10 <property name="username" value="***"/> 11 <property name="password" value="***"/> 12 </bean> 13 <bean id="daoImpl" class="com.xfwl.spring.DI.LoginDaoImp"> 14 <property name="dao" ref="dao"/> 15 </bean>
三、接口注入
接口注入,關鍵是將第三方的外部資源注入到到咱們想要的地方,關鍵是如何把數據信息注入到第三方資源對象中,而後再把第三方資源對象注入到指定的地方。
關鍵點在於配置文件:
1 <!-- 依賴注入·接口注入 --> 2 <!-- 配置數據源,使用C3P0鏈接池 的接口注入實現--> 3 <bean id="dataSource" 4 class="com.mchange.v2.c3p0.ComboPooledDataSource"> 5 <property name="driverClass" value="${jdbc.driverClass}"></property> 6 <property name="jdbcUrl" value="${jdbc.url}"></property> 7 <property name="user" value="${jdbc.username}"></property> 8 <property name="password" value="${jdbc.password}"></property> 9 <!-- 指定鏈接池中保留的[最大鏈接數]. Default:15--> 10 <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/> 11 <!-- 指定鏈接池中保留的[最小鏈接數]--> 12 <property name="minPoolSize" value="${jdbc.minPoolSize}"/> 13 <!-- 指定鏈接池的初[始化鏈接數] 取值應在minPoolSize 與 maxPoolSize 之間.Default:3--> 14 <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/> 15 <!-- [最大空閒時間],60秒內未使用則鏈接被丟棄。若爲0則永不丟棄。 Default:0--> 16 <property name="maxIdleTime" value="${jdbc.maxIdleTime}"/> 17 <!-- 當鏈接池中的鏈接耗盡的時候c3p0[一次同時獲取的鏈接數]. Default:3--> 18 <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/> 19 <!-- 20 JDBC的標準,用以控制數據源內加載的PreparedStatements數量。 21 但因爲預緩存的statements屬於單個connection而不是整個鏈接池因此設置這個參數須要考慮到多方面的因數. 22 若是maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default:0 23 --> 24 <property name="maxStatements" value="${jdbc.maxStatements}"/> 25 <!-- 每60秒檢查全部鏈接池中的[空閒鏈接].Default:0 --> 26 <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/> 27 </bean>
稍微分析一下:
id:SpringIoc容器中配置的Bean對象。
class:第三方資源對象的接口全路徑。
property :注入到第三方資源對象的數據。
建立一個測試類:TestBean.java
1 package com.xfwl.spring.DI; 2 import java.sql.SQLException; 3 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 import org.springframework.context.support.FileSystemXmlApplicationContext; 7 8 /** 9 * Spring Ioc測試 10 * @function 11 * @author 小風微涼 12 * @time 2018-7-10 上午9:55:15 13 */ 14 public class TestBean { 15 //絕對路徑:FileSystemXmlApplicationContext 16 private static final String xmlAbsPath="E:/JAVA學習[【進階學習】/JAVA回爐深造/進階測試工做空間/多線程/SpringSources/src/com/xfwl/spring/DI/applicationContext.xml"; 17 //項目相對路徑:ClassPathXmlApplicationContext/ApplicationContext 18 private static final String xmlRelPath="com/xfwl/spring/DI/applicationContext.xml"; 19 public static void main(String[] args) throws SQLException { 20 //拿到解析對象 21 ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext(xmlRelPath); 22 //【1】構造器注入-拿到Bean對象 23 //UserBean user=(UserBean) ctx.getBean("user_xfwl"); 24 //System.out.println(user.toString()); 25 //【2】setter注入-拿到Bean對象 26 //Administrators admin=(Administrators) ctx.getBean("admin_xfwl"); 27 //System.out.println(admin.toString()); 28 //【3】接口注入-拿到Bean對象 29 LoginDaoImp daoImpl=(LoginDaoImp) ctx.getBean("daoImpl"); 30 daoImpl.queryCstListByNo("CB10000929"); 31 32 } 33 }
測試結果:通過數據脫敏後的結果顯示
1 log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). 2 log4j:WARN Please initialize the log4j system properly. 3 log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 4 企業客戶號:CB10000929,核心客戶號:***********客戶名稱:賞渝沃舜汪物技術柔限星司, 5 企業客戶號:CB10000764,核心客戶號:***********客戶名稱:李靖, 6 企業客戶號:CB10000720,核心客戶號:***********客戶名稱:李靖333, 7 企業客戶號:CB10000926,核心客戶號:***********客戶名稱:賞渝沃舜汪物技術柔限星司, 8 企業客戶號:CB10000927,核心客戶號:***********客戶名稱:賞渝沃舜汪物技術柔限星司, 9 企業客戶號:CB10000931,核心客戶號:***********客戶名稱:賞渝沃舜汪物技術柔限星司, 10 企業客戶號:CB10000940,核心客戶號:***********客戶名稱:賞渝沃舜汪物技術柔限星司,