ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring 依赖注入

2019-08-21 16:03:04  阅读:266  来源: 互联网

标签:依赖 set Spring void SpellChecker TextEditor public 注入


Spring 依赖注入

依赖注入有两种方式:

  • 通过构造方法来注入
  • 通过get、set方法

接下来我们直接通过代码来展示这两种方式

通过构造函数方法注入

需要被注入SpellChecker的TextEditor类

package com.tutorialspoint;

public class TextEditor {
	private SpellChecker spellChecker;
	
	public TextEditor(SpellChecker spellChecker) {
		this.spellChecker = spellChecker;
        System.out.println("创建了 TextEditor 实例");
	}
	
	public void spellCheck() {
		spellChecker.checkSpelling();
	}
	
}

注入对象SpellChecker

package com.tutorialspoint;

public class SpellChecker {
	
	public SpellChecker() {
		System.out.println("使用SpellChecker() 创建了SpellChecker对象");
	}
	
	public void checkSpelling() {
		System.out.println("调用了 checkSpelling() 方法");
	}
}

在Beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
		<constructor-arg ref="spellChecker" />
    </bean>
    
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">  
    </bean>

</beans>

测试

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApp {
	public static void main(String[] arg) {
		
		ApplicationContext  context = new FileSystemXmlApplicationContext("src/Beans.xml");
		
		TextEditor obj1 = (TextEditor)context.getBean("textEditor");
		
		obj1.spellCheck();
	
	}
}
/*
输出

使用SpellChecker() 创建了SpellChecker对象
创建了 TextEditor 实例
调用了 checkSpelling() 方法

*/

在TextEditor中有属性类型为SpellChecker,他俩存在依赖注入,这次是通过构造函数的方式注入,注入过程中,先创建了 SpellChecker对象,然后再创建 TextEditor 实例,然后将依赖注入,这里要注意他们的顺序关系

构造函数参数解析

  • 对于多个参数的构造,如下面的这种情况
package x.y;
public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}

按照参数的顺序給值

<beans>
   <bean id="foo" class="x.y.Foo">
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
   </bean>

   <bean id="bar" class="x.y.Bar"/>
   <bean id="baz" class="x.y.Baz"/>
</beans>

这样的配置可以正确运行

  • 对于不同类型的参数,如:
package x.y;
public class Foo {
   public Foo(int year, String name) {
      // ...
   }
}

使用 type 属性显式的指定了构造函数参数的类型

<beans>

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg type="int" value="2001"/>
      <constructor-arg type="java.lang.String" value="Zara"/>
   </bean>

</beans>

这种方式也可以按照我们预期的正确执行

  • 最好的方式是 使用 index 属性来显式的指定构造函数参数的索引,像这样:
<beans>

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg index="0" value="2001"/>
      <constructor-arg index="1" value="Zara"/>
   </bean>

</beans>

最后,如果你想要向一个对象传递一个引用,你需要使用 标签的 ref 属性,如果你想要直接传递值,那么你应该使用如上所示的 value 属性。

最好的方式是 使用 index 属性来显式的指定构造函数参数的索引

基于设值函数的依赖注入

​ 当容器调用一个无参的构造函数或一个无参的静态 factory 方法来初始化你的 bean 后,通过容器在你的 bean 上调用设值函数,基于设值函数的 DI 就完成了。

​ 与 Java POJO 类非常相似

示例

package com.tutorialspoint;

public class SpellChecker {
	
	public SpellChecker() {
		System.out.println("创建了SpellChecker对象");
	}
	
	public void checkSpelling() {
		System.out.println("调用了 checkSpelling() 方法");
	}

}
-------------------------------------
package com.tutorialspoint;

public class TextEditor {
	private SpellChecker spellChecker;
	
	public void setSpellChecker(SpellChecker spellChecker) {
		this.spellChecker = spellChecker;
		System.out.println("注入了 SpellChecker 对象 到 TextEditor中了");
	}
	
	public void spellCheck() {
		spellChecker.checkSpelling();
	}
	
}
-------------------------------------------
package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApp {
	public static void main(String[] arg) {
		
		ApplicationContext  context = new FileSystemXmlApplicationContext("src/Beans.xml");
		
		TextEditor obj1 = (TextEditor)context.getBean("textEditor");
		
		obj1.spellCheck();
	
	}
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
		<property name="spellChecker" ref="spellChecker"></property>
    </bean>  
    
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">  
    </bean>
</beans>

相比通过构造方法注入,基于设置函数的依赖注入方式,示例改动的地方有:

  • 在TextEditor中增加了一个设置值的方法setSpellChecker
  • 在Beans配置文件中,将标签<constructor-arg>,换成了<property name="spellChecker" ref="spellCheck"></property>,这一点很关键

输出

创建了SpellChecker对象
注入了 SpellChecker 对象  TextEditor中了
调用了 checkSpelling() 方法

可以看到成功的注入了

如果需要设置较多的参数,那么有一种方式可以减少很多代码 p-namespace

假如以下是原来的配置方式:

<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-3.0.xsd">

   <bean id="john-classic" class="com.example.Person">
      <property name="name" value="John Doe"/>
      <property name="spouse" ref="jane"/>
   </bean>

   <bean name="jane" class="com.example.Person">
      <property name="name" value="John Doe"/>
   </bean>

</beans>

我们使用 p-namespace 做简化

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="john-classic" class="com.example.Person"
      p:name="John Doe"
      p:spouse-ref="jane"/>
   </bean>

   <bean name="jane" class="com.example.Person"
      p:name="John Doe"/>
   </bean>

</beans>

我们看到代码大大减少了

-ref 部分表明这不是一个直接的值,而是对另一个 bean 的引用。

注入内部Bean

对于注入,还有另外一种,写法,可以基于注入内部bean的方式

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
		<property name="spellChecker">
   			 <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"></bean>
        </property>
    
</beans>

还可以通过propreties来注入

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
		<property name="spellChecker" ref="spellChecker"></property>
        
        <!-- 注意,这里注入的属性,类型必须 为 ProPerties -->
		<property name="properties">
			<value>
				propertiesName=i'm properties.
			</value>
		</property>
    </bean>
    
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">  
    </bean>

</beans>

对应的注入类,应该这样写

package com.tutorialspoint;

import java.util.Properties;

public class TextEditor {
	private SpellChecker spellChecker;
	private Properties properties;
	
	public void setSpellChecker(SpellChecker spellChecker) {
		this.spellChecker = spellChecker;
		System.out.println("注入了 SpellChecker 对象 到 TextEditor中了");
	}

    //增加一个set方法
	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	public void spellCheck() {
		spellChecker.checkSpelling();
		
        //输出 注入的 propreties 值
		System.out.println("propertiesName = " + properties.getProperty("propertiesName"));
	}
	
}

总结一下

  • 首先在要注入的类中有提供 setXxx 方法。
  • 然后在Beans.xml中配置注入,其中写法有好几种
  • 普通的xml写法<prototype name="..." value/ref="..." />,基本类型用value,引用另一个bean用ref
  • 可以注入内部类bean :在<prototype> <bean .....> </bean> </prototype>的中间写,bean
  • 还可以注入properties,类型的bean。要求被注入的属性类型必须是Properties类型的

注入集合

​ 如果你想传递多个值,如 Java Collection 类型 List、Set、Map 和 Properties,应该怎么做呢。Spring 提供了四种类型的集合的配置元素, <list/>, <set/>, <map/>, 和<props/>

元素 描述
它有助于连线,如注入一列值,允许重复。
它有助于连线一组值,但不能重复。
它可以用来注入名称-值对的集合,其中名称和值可以是任何类型。
它可以用来注入名称-值对的集合,其中名称和值都是字符串类型。

我们们下来直接看示例

准备好要被注入的对象,里面包含各种注入的类型,以及setXxx方法

package com.tutorialspoint;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class TextEditor {
	private List list;
	private Set set;
	private Map map;
	private Properties addProperties;
	
	
	public void setList(List list) {
		this.list = list;
	}
	public void setSet(Set set) {
		this.set = set;
	}
	public void setMap(Map map) {
		this.map = map;
	}
	public void setAddProperties(Properties addProperties) {
		this.addProperties = addProperties;
	}
	@Override
	public String toString() {
		return "TextEditor [list=" + list + ", set=" + set + ", map=" + map + ", addProperties=" + addProperties + "]";
	}
	
}

在Beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    	<property name="list">
    		<list>
    			<value> list value 1 </value>
    			<value> list value 2 </value>
    		</list>
    	</property>
    	
    	<property name="set">
			<set>
				<value> set value 1</value>
				<value> set value 2</value>
			</set>    	
    	</property>
    
    	<property name="map">
    		<map>
    			<entry key="mapKey1" value="mapValue1"></entry>
    			<entry key="mapKey2" value="mapValue2"></entry>
    		</map>
    	</property>
    
    	<property name="addProperties">
    		<props>
    			<prop key="propKey1">propValue 1</prop>
    			<prop key="propKey2">propValue 2</prop>
    		</props>
            <!--   这样写也能实现相同的功能,但是两者不可以都有-->    		
            <!-- <value>
    			propKey1 = propValue 1
    			propKey2 = propValue 2
    		</value> -->
    	</property>
    
    </bean>
</beans>

测试一下

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApp {
	public static void main(String[] arg) {
		
		ApplicationContext  context = new FileSystemXmlApplicationContext("src/Beans.xml");
		
		TextEditor obj1 = (TextEditor)context.getBean("textEditor");
		
		System.out.println(obj1.toString());
	
	}
}
/*
TextEditor [list=[ list value 1 ,  list value 2 ], set=[ set value 1,  set value 2], map={mapKey1=mapValue1, mapKey2=mapValue2}, addProperties={propKey2=propValue 2, propKey1=propValue 1}]
*/

可以看到,值成功的注入了对象

在集合中注入bean的引用

我们来看复杂一些的例子

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    	<property name="list">
    		<list>
    			<value> list value 1 </value>
    			<ref bean="address1"></ref>
    			<ref bean="address2"></ref>
    		</list>
    	</property>
    	
    	<property name="set">
			<set>
				<value> 1</value>
				<value>2</value>
				<ref bean="address1"></ref>
    			<ref bean="address2"></ref>
			</set>    	
    	</property>
    
    	<property name="map">
    		<map>
    			<entry key="mapKey1" value="mapValue1"></entry>
    			<entry key="mapKey2" value="mapValue2"></entry>
    			<entry key="mapKey3" value-ref="address1"></entry>
    			<entry key="mapKey4" value-ref="address2"></entry>
    		</map>
    	</property>
    
    	<property name="addProperties">
    		<props>
    			<prop key="propKey1">propValue 1</prop>
    			<prop key="propKey2">propValue 2</prop>
    		</props> 
<!--     		这样写也能实现相同的功能,但是两者不可以都有
 -->    		<!-- <value>
    			propKey1 = propValue 1
    			propKey2 = propValue 2
    		</value> -->
    	</property>
    </bean>
    
    <bean id="address1" class="com.tutorialspoint.Address1"></bean>
    <bean id="address2" class="com.tutorialspoint.Address2"></bean>
    
</beans>

我们看到在,list,set,map中都增加了bean引用

  • 对于list 和 set,使用 <ref bean="address2"></ref>
  • 对于map,使用 <entry key="mapKey3" value-ref="address1"></entry>
  • props 只能是字符串类型的,不支持引用

注入null

<bean id="..." class="exampleBean">
   <property name="email" value=""/>
</bean>

相当于 Java 代码:exampleBean.setEmail("")

注入""空字符串

<bean id="..." class="exampleBean">
   <property name="email"><null/></property>
</bean>

相当于 Java 代码:exampleBean.setEmail(null)

标签:依赖,set,Spring,void,SpellChecker,TextEditor,public,注入
来源: https://blog.csdn.net/the_power/article/details/99969482

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有