一、 Spring中的依赖注入
依赖注入:Dependency Injection
IOC的作用:
降低程序间的依赖关系(耦合)
依赖关系的管理
以后都交给spring来维护
在当前需要用到其他类的对象 由spring为我们提供 我们只需要在配置文件中说明
依赖关系的维护:
就称为依赖注入
依赖注入
能注入的数据有三类:
基本类型和String
其他bean类型(在配置文件中 或注解配置过得属性)
复杂类型 集合类型
二、注入方式 三种
1.构造函数注入
构造函数注入 实际开发很少用
使用的标签 constructor-arg
标签出现的位置:bean标签的内部
标签中的属性
type:用于指定要注入的数据类型 该数据类型也是构造函数中某个或某些数据类型 无法独立实现功能
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值 索引的位置是从0开始 可以独立 实现功能
name:用于指定给构造函数中指定名称的参数赋值 常用的是name
=以上三个用于指定给构造函数中那个参数赋值========
value:用于提供基本类型和string类型的数据
ref:用于指定其他的bean类型数据 它指的就是在spring的ioc核心容器中出现过的bean对象
优势:在获取bean对象时,注入数据是必须的操作 否则对象无法创建成功
缺点:改变了bean对象的实例化方式,使我们在创建对象时 如果用不到这些数据 也必须提供
<bean id="accountService" class="com.rpf.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="test"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<!--配置一个日期对象-->
<bean id="now" class="java.util.Date"></bean>
业务实现类
//如果是经常变化的数据 并不适用于注入的方式
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name,Integer age,Date birthday){
this.name=name;
this.age=age;
this.birthday=birthday;
}
public AccountServiceImpl(){
System.out.println("对象创建了");
}
public void saveAccount(){
System.out.println("service 中的save执行了"+name+","+age+","+birthday);
}
测试控制层调用
AccountService as = (AccountService)ac.getBean("accountService");
as.saveAccount();
2.使用set方法提供
bean.xml
<!--set方法注入 更常用的方式
涉及的标签property
出现的位置bean标签内部
标签的属性
name:用于指定注入时所需要的用的set方法名称 常用的是name
value:用于提供基本类型和string类型的数据
ref:用于指定其他的bean类型数据 它指的就是在spring的ioc核心容器中出现过的bean对象
优势:创建对象时没有明确的限制 可以直接使用构造函数
弊端:如果某个成员必须有值 则获取对象时有可能set方法没有执行
-->
<bean id="accountService2" class="com.rpf.service.impl.AccountServiceImpl2">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
业务实现类
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void saveAccount(){
System.out.println("service 中的save执行了"+name+","+age+","+birthday);
}
}
测试控制层调用
AccountService as = (AccountService)ac.getBean("accountService2");
as.saveAccount();
3.复杂类型注入
bean.xml
<!--复杂类型的注入/集合类型的注入
用于给List结构集合注入的标签:
list array set(可以互换)
用于给map集合注入的标签有:
结构相同标签可以互换
map props(可以互换)
-->
<bean id="accountService3" class="com.rpf.service.impl.AccountServiceImpl3">
<property name="myStrs">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<property name="myList">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<property name="mySet">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<property name="myMap">
<props>
<prop key="testD">AAA</prop>
<prop key="testE">DDD</prop>
</props>
</property>
<property name="myProps">
<map>
<entry key="testA" value="AAA"></entry>
<entry key="testB">
<value>BBB</value>
</entry>
<entry key="testC" value="CCC"></entry>
</map>
</property>
</bean>
业务实现类
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties myProps;
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
public void saveAccount(){
System.out.println(Arrays.toString(myStrs));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
System.out.println(myProps);
}
测试
AccountService as = (AccountService)ac.getBean("accountService3");
as.saveAccount();
三、扩展方式注入
扩展一个c命名空间注入个P命名空间注入
官方文档提到的注入方式
使用命名空间注入方式Spring的xml文件必须要导入约束
<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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
我们创建一个实体类User用于测试
package com.rpf.pojo;
/**
* @create: 2021/6/18
* @author: Tony Stark
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试P命名空间注入的方式
编写xml文件注入
<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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间注入可以直接注入属性的值-->
<bean id="user" class="com.rpf.pojo.User" p:name="飞飞" p:age="22"></bean>
</beans>
这里在类的全路径之后 打 p:
就会提示我们实体类中的信息 选中赋值即可
测试
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
结果如下
注入成功!!!!
测试C命名空间注入的方式
xml配置文件配置
<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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--c命名空间注入通过构造器注入 construct-args 构造器参数-->
<bean id="user2" class="com.rpf.pojo.User" c:age="18" c:name="飞飞"></bean>
</beans>
在类的全限定路径后打C:
就会提示我们如下信息
由于我们的C命名空间注入方式是依靠构造函数注入 所以我们必须在实体类加入有参无参构造
package com.rpf.pojo;
/**
* @create: 2021/6/18
* @author: Tony Stark
*/
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试注入是否成功
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
结果如下:
注入成功!!!
最后附上测试命名空间命名方式的maven依赖和完整配置文件 与实体类
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
package com.rpf.pojo;
/**
* @create: 2021/6/18
* @author: Tony Stark
*/
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}