基于构造器的注入;基于setter方法的注入;注解注入
一、基于构造器的依赖注入
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">
<!--我们可以将xml文件理解位ioc容器,我们将需要创建对象的类注入到xml文件中也就是ioc容器里,当我们需要时从中取出即可,这样当需求改变时我们不需要修改源代码,只需要修改xml配置文件即可.
-->
<!--JpaAccountDao accountDao = new JpaAccountDao();
一个bean相当于上面一个创建对象的语句
bean标识符中id等价于accountDao
class等价于new JpaAccountDao();这里clss要写具体路径
如果有属性即变量的话,用property标识符,<property name = "age" value = "15"/>
等价于age = 15;
-->
<bean id="accountDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for data access objects go here -->
</beans>
注入
//首先,给出一个POJO类,不依赖于特定于容器的接口,基类或注释
package examples;
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private int years;
// The Answer to Life, the Universe, and Everything
private String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
1、构造函数参数类型匹配
在上述情况下,如果通过使用type属性显式指定构造函数参数的类型,则容器可以使用简单类型的类型匹配。如以下示例所示:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
2、构造函数参数索引
您可以使用该index属性来明确指定构造函数参数的索引,如以下示例所示:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
二、基于setter的依赖注入
通过使用无参数构造函数或无参数static工厂方法实例化bean之后,容器通过在bean上调用setter方法来实现基于setter的DI;也就是说注入bean中的类只能有无参构造方法或是实例化无参static工厂,ioc会通过调用setter方法来实现依赖注入,如果没有setter方法,xml会报错。
//给出一个pojo类
public class ExampleBean {
private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;
public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}
public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}
public void setIntegerProperty(int i) {
this.i = i;
}
}
//注入
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested ref element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>//不懂这个的看一下元素<ref/>
</property>
<!-- setter injection using the neater ref attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
以上两种都是在xml配置文件中进行依赖注入(DI:Dependency Injection)
三、注解注入
//JAVA配置
@Confirguration //相当于spring的配置文件XML
@Bean //用到方法上,表示当前方法的返回值是一个bean
java配置是使用java配置类,这个类的作用和xml一样,只是依赖注入方式不同。大致是一样的,不再详细介绍;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JavaConfig {
//通过这种方式,获得spring的依赖注入
//一个@Bean相当于xml中的一个<bean></bean>
@Bean
public UseFunctionService useFunctionService () {
return new UseFunctionService ();
}
@Bean
.
.
.
}
这种方式是通过java类加上注解进行依赖注入
四、p-namespace和c-namespace
4.1具有p-namespace的XML快捷方式
使用p-namespace,可以使用bean元素的属性来描述协作Bean的属性值,而不是嵌套 元素,,也可以同时使用这两者。
Spring支持具有名称空间的可扩展配置格式,这些名称空间基于XML Schema定义。beans本章讨论的配置格式在XML Schema文档中定义。但是,p命名空间未在XSD文件中定义,仅存在于Spring的核心中。
下面的示例显示了两个XML代码段(第一个使用标准XML格式,第二个使用p-命名空间),它们可以解析为相同的结果:
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="classic" class="com.example.ExampleBean">
<property name="email" value="someone@somewhere.com"/>
</bean>
<bean name="p-namespace" class="com.example.ExampleBean"
p:email="someone@somewhere.com"/>
</beans>
该示例显示了email在bean定义中调用的p-namespace中的属性。这告诉Spring包含一个属性声明。如前所述,p名称空间没有架构定义,因此您可以将属性的名称设置为属性名称。
下一个示例包括另外两个bean定义,它们都引用了另一个bean:
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="john-classic" class="com.example.Person">
<property name="name" value="John Doe"/>
<property name="spouse" ref="jane"/>
</bean>
<bean name="john-modern"
class="com.example.Person"
p:name="John Doe"
p:spouse-ref="jane"/>
<bean name="jane" class="com.example.Person">
<property name="name" value="Jane Doe"/>
</bean>
</beans>
p命名空间不如标准XML格式灵活。例如,用于声明属性引用的格式与以结尾的属性发生冲突Ref,而标准XML格式则没有。我们建议您谨慎选择方法,并将其传达给团队成员,以避免同时使用这三种方法生成XML文档。
4.2具有c-namespace的XML快捷方式
与具有p-namespace的XML Shortcut相似,在Spring 3.1中引入的c-namespace允许使用内联属性来配置构造函数参数,而不是嵌套constructor-arg元素。
以下示例使用c:名称空间执行与 基于构造函数的依赖注入相同的操作:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
<!-- traditional declaration with optional argument names -->
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg name="thingTwo" ref="beanTwo"/>
<constructor-arg name="thingThree" ref="beanThree"/>
<constructor-arg name="email" value="something@somewhere.com"/>
</bean>
<!-- c-namespace declaration with argument names -->
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
</beans>
该c:命名空间使用相同的约定作为p:一个(尾部-ref的bean引用),供他们的名字设置构造函数的参数。同样,即使未在XSD模式中定义它(也存在于Spring内核中),也需要在XML文件中声明它。
对于极少数情况下无法使用构造函数自变量名称的情况(通常,如果字节码是在没有调试信息的情况下编译的),则可以对参数索引使用后备,如下所示:
<!-- c-namespace index declaration -->
<bean id="beanOne" class="x.y.ThingOne" c:_0-ref="beanTwo" c:_1-ref="beanThree"
c:_2="something@somewhere.com"/>
由于XML语法的原因,索引符号要求使用前导_,因为XML属性名称不能以数字开头(即使某些IDE允许)。相应的索引符号也可用于元素,但并不常用,因为声明的简单顺序通常就足够了。