其他分享
首页 > 其他分享> > Spring 依赖注入

Spring 依赖注入

作者:互联网

Spring 依赖注入

依赖注入有两种方式:

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

通过构造函数方法注入

需要被注入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>

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

<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>

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

输出

创建了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"));
	}
	
}

总结一下

注入集合

​ 如果你想传递多个值,如 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引用

注入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