Spring Framework学习之DI——依赖注入
目录
- setter注入
- 注入匿名内部bean
- 注入集合类型属性
- 注入null、空字符串类型属性值
- 注入复合属性值
- 两个关联的java类
- xml配置注入复合属性
- 获取注入复合属性的属性值
- 注入外部properties文件中的属性值
- jdbc.properties
- xml配置引入外部的properties文件
- 通过p命名空间注入属性
- 要想使用p命名空间,必须要加相应的p的schema
- 通过p命名空间来注入属性
- 构造方法注入
- constructor-arg标签属性
- 通过c命名空间注入构造参数
- 自动装配
- byName和byType方式
- java bean类
- xml配置
- 程序运行入口
- constructor方式
- java bean类
- xml配置
- 程序运行入口
- 将某个bean从自动装配候选中排除
Spring 依赖注入(DI Dependency Injection),可以自动帮我们解决类与类之间的各种依赖问题。通常公司中的项目都包含很多的类,而这些类与类之间都有各种依赖关系,比如:组合、聚合、依赖等。通过Spring的DI功能,结合IOC容器, 我们可以把这些复杂的关系交由Spring来管理, 我们在使用时,Spring会自动帮我们把依赖的对象注入进来,大大降低开发难度。
Spring中的依赖注入主要包含两种:通过构造方法中的注入和通过Setter方法注入
setter注入
注入匿名内部bean
内部bean不需要指定id、name属性,如果指定了也无法在外部直接获取,另外内部bean也不支持scope属性,因为内部bean始终是由外部bean创建的,并且只能在外部bean中使用
<!-- 给Student注入一个匿名内部bean -->
第一种:
<!-- setter注入 -->
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="fruit">
<bean class="com.lanou3g.spring.simple.Apple" >
<property name="kind" value="CyanApple"
</bean>
</property>
</bean>
第二种:
<!-- 构造方法注入 -->
<bean id="student" class="com.lanou3g.spring.bean.Student">
<constructor-argname="fruit">
<bean class="com.lanou3g.spring.simple.Apple" >
<property name="kind" value="CyanApple"
</bean>
</property>
</bean>
注入集合类型属性
<!-- 注入集合、Map类型参数 -->
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="hobbies">
<list>
<!-- 普通元素 -->
<value>游泳</value>
<value type="java.lang.Integer">0034</value>
<!-- 引用类型元素 -->
<ref bean="study" />
</list>
</property>
<property name="gameTitles">
<map>
<entry key="LOL" value="嘴强王者"></entry>
<entry key="王者农药" value="甩锅大神"></entry>
<entry key="和平精英" value="菜鸡"></entry>
</map>
</property>
</bean>
注入null、空字符串类型属性值
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="age" value="" />
</bean>
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="age">
<null />
</property>
</bean>
注入复合属性值
两个关联的java类
@Setter
@Getter
public class People{
private Student student;
}
@Setter
@Getter
public class Student{
private Integer age;
}
xml配置注入复合属性
<bean id="people" class="com.lanou3g.spring.bean.People">
<property name="student" ref="student" />
<property name="student.age" value="23" />
</bean>
<bean id="student" class="com.lanou3g.spring.bean.Student" />
获取注入复合属性的属性值
public static void main( String[] args ) {
ApplicationContext cpxac = new AnnotationConfigApplicationContext(App.class);
People people = cpxac.getBean(People.class);
System.out.println(people.getStudent().getAge());
}
注入外部properties文件中的属性值
jdbc.properties
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=root
jdbc.maxIdle=3
jdbc.minIdle=1
jdbc.maxActive=10
xml配置引入外部的properties文件
<!-- 方式一 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
<!-- 方式二 -->
<!-- 通过方式二这种方式和方式一等效,推荐使用 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 无论用方式一还是方式二都需配置下面的节点 -->
<!-- 将外部properties文件中的属性注入到bean中 -->
<bean id="jdbcConf" class="com.lanou3g.spring.bean.JDBCConf">
<property name="url" value="${jdbc.url}" />
<property name="driver" value="${jdbc.driver}" />
<property name="userName" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
通过p命名空间注入属性
要想使用p命名空间,必须要加相应的p的schema
xmlns:p="http://www.springframework.org/schema/p"
通过p命名空间来注入属性
<!--<bean id="yunjie1" class="com.lanou3g.spring.bean.Student">
<property name="sname" value="张三" />
</bean>-->
<!-- 等效于上面的配置 -->
<bean id="yunjie1" class="com.lanou3g.spring.bean.Student" p:sname="张三" />
构造方法注入
package x.y;
public class ThingOne {
private int age;
private String sname;
private int gender;
private ThingTwo thingTwo;
public ThingOne(int age, ThingTwo thingTwo, String sname, int gender) {
this.age = age;
this.thingTwo = thingTwo;
this.sname = sname;
this.gender = gender;
// ...
}
}
public class ThingTwo {
// ...
}
<beans>
<!-- 有参注入 -->
<bean id="beanOne" class="x.y.ThingOne">
<!-- 通过此标签注入构造方法中的参数 -->
<constructor-arg name="age" value="18" />
<constructor-arg type="java.lang.String" value="张三" />
<constructor-arg ref="beanTwo"/>
</bean>
<!-- 无参注入 -->
<bean id="beanTwo" class="x.y.ThingTwo"/>
</beans>
constructor-arg标签属性
属性名 | 取值 | 含义 |
---|---|---|
name | 字符串 | 构造参数的名称 |
value | 数值、字符串 | 构造参数的属性值,只适用于简单类型 |
type | 类的全名 | 构造参数的类型,如果是简单类型,需要指定对应的封装类型 如果构造参数中有多个命中的类型,按照配置的先后顺序注入(可以通过配合index属性改变默认顺序) |
index | 数值 | 构造参数的位置,从0开始 |
ref | 其他在Spring容器中配置的bean的name或者id | 将容器中的其他bean作为构造参数注入 |
通过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"/>
<!-- 传统方式注入构造参数 -->
<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命名空间方式注入构造参数 -->
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
</beans>
自动装配
自动装配允许我们不用显示给某个bean注入依赖的属性或者构造参数,而交由Spring自动帮我们注入所需的依赖。
Spring给我们提供了以下四种选项
自动装配模式 | 说明 |
---|---|
no | (默认值) 禁止Spring帮我们自动装配依赖,所有依赖由开发者显示注入。 |
byName | 按照bean的名称注入。比如beanA有一个属性beanB需要注入,如果beanA配置了自动装配模式是byName,那么Spring会在容器中找bean的名称为beanB的bean,找到后自动帮我们注入到beanA中。如果没找到,则不会注入。 |
byType | 按照bean的类型注入。byType模式需要保证容器中符合注入的类型的bean只有一个,如果匹配的类型有不止一个bean,那么会直接抛出运行时异常。如果没有一个匹配类型的bean,则不会注入。 |
constructor | 类似于byType。但这种模式应用的对象是构造参数。如果构造参数需要注入参数类型的bean有不止一个,同样会抛出运行时异常。 |
byName和byType方式
java bean类
@Setter
@Getter
public class People {
private String pname;
private Student student;
}
@Setter
@Getter
public class Student {
private int age;
}
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.xsd">
<!-- 给Student类中的age属性赋值 -->
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="age" value="25" />
</bean>
<!-- byName方式 -->
<bean id="peopleByName" class="com.lanou3g.spring.bean.People"
autowire="byName">
<property name="pname" value="张三" />
</bean>
<!-- byType方式 -->
<bean id="peopleByType" class="com.lanou3g.spring.bean.People"
autowire="byType">
<property name="pname" value="张三" />
</bean>
</beans>
程序运行入口
public class App {
public static void main( String[] args ) {
ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
cpxac.registerShutdownHook();
// 按照名称自动注入属性
People peopleByName= cpxac.getBean("peopleByName" , People.class);
System.out.println("byName名字: " + peopleByName.getPname());
System.out.println("byName学生年龄:" + peopleByName.getStudent().getAge());
// 按照名称自动注入属性
People peopleByType= cpxac.getBean("peopleByType" , People.class);
System.out.println("byType名字: " + peopleByType.getPname());
System.out.println("byType学生年龄:" + peopleByType.getStudent().getAge());
}
}
constructor方式
java bean类
@Setter
@Getter
public class People {
private String pname;
private Student student;
public People() {
}
public People(Student student) {
this.student = student;
}
}
@Setter
@Getter
public class Student {
private int age;
}
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.xsd">
<!-- 给Student类中的age属性赋值 -->
<bean id="student" class="com.lanou3g.spring.bean.Student">
<property name="age" value="25" />
</bean>
<!-- byConstructor方式 -->
<bean id="peopleByConstructor" class="com.lanou3g.spring.bean.People"
autowire="constructor">
<property name="pname" value="张三" />
</bean>
</beans>
程序运行入口
public class App {
public static void main( String[] args ) {
ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
cpxac.registerShutdownHook();
// 按照名称自动注入属性
People peopleByConstructor = cpxac.getBean("peopleByConstructor" , People.class);
System.out.println("ByConstructor名字: " + peopleByConstructor.getPname());
System.out.println("ByConstructor学生年龄:" + peopleByConstructor.getStudent().getAge());
}
}
将某个bean从自动装配候选中排除
我们可以通过给bean添加autowire-candidate属性,并且设置为false,从而让这个bean不参与自动装配(不会被自动装配到其他bean上)
还没有评论,来说两句吧...