Spring详解-------依赖注入的三种方式实例详解
Posted 「已注销」
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring详解-------依赖注入的三种方式实例详解相关的知识,希望对你有一定的参考价值。
目录
1、什么是依赖注入
DI (Dependency Injection):依赖注入是指在 Spring IOC 容器创建对象的过程中,将所依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。 在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护成本越高,因此对象的设计应使对象之间的耦合越小越好。1.1类的关系
继承 实现 依赖 关联 聚合 组合1.1.1 依赖关系(Dependency)
【依赖关系】:是一种使用的关系 , 即一个类的实现需要另一个类的协助 , 所以要尽量不使用双向的互相依赖 【代码表现】:局部变量、方法的参数或者对静态方法的调用 【箭头及指向】:带箭头的虚线,指向被使用者1.1.2 聚合(Aggregation)
【聚合关系】:是整体与部分的关系 . 如车和轮胎是整体和部分的关系.聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分, 必须考察具体的逻辑关系。 【代码体现】:成员变量 【箭头及指向】:带空心菱形的实心线,菱形指向整体1.2关系强度
继承 = 实现 > 组合 > 聚合 > 关联 > 依赖2 为什么使用依赖注入
2.1开闭原则
2.1.1 定义
OCP (Open Close Principle): 软件本身应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。2.1.2 开闭原则优点
- 易扩展。开闭原则的定义就要求对扩展开放。
- 易维护。软件开发中,对现有代码的修改是一件很有风险的事情,符合开闭原则的设计
- 在扩展时无需修改现有代码,规避了这个风险,大大提交了可维护性。
2.2高内聚,低耦合
高内聚是指相关度比较高的部分尽可能的集中,不要分散。 低耦合就是说两个相关的模块尽可以能把依赖的部分降低到最小,不要产生强依赖。3 依赖注入的方式
在使用依赖注入时,如果注入的是 Bean 对象,那么要求注入的 Bean 对象与被注入的 Bean 对象都需要 Spring IOC 容器来实例化。 依赖注入的方式有通过set方式注入、通过构造方法注入、自动注入。 持久层的代码比较少,后面的多个注入方式比较多,持久层代码就不重复写,后面的set注入方式、构造方法注入方式、自动注入方式的所有的持久层代码都使用下面的这一个。 持久层userDao接口public interface UserDao
void InitUserDao();
持久层userDaoIml实现
public class UserDaoImpl implements UserDao
@Override
public void InitUserDao()
System.out.println("InitUserDao......");
3.1通过 Set 方法注入
持久层的UserDao使用上面的内容。
业务层UserService接口
public interface UserService
public void addUser();
业务层UserServiceImpl实现
使用set方法进行依赖注入的时候必须给需要注入的对象创建set方法
public class UserServiceImpl implements UserService
private UserDao userDao;
//使用set方法实现依赖注入
public void setUserDao(UserDao userDao)
this.userDao = userDao;
@Override
public void addUser()
userDao.InitUserDao();
System.out.println("UserService........addUser");
配置文件(配置UserServiceImpl对象)
<?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">
<!--配置UserServiceImpl对象-->
<!--bean中的name属性可以有多个值,多个值可以使用逗号分隔开.(name属性不是必须的)-->
<bean id="userService" name="name1,name2,name3" class="com.xjx.service.impl.UserServiceImpl"/>
</beans>
测试依赖注入(测试UserDao是否注入成功)
public class UserServiceTest
public static void main(String[] args)
//启动IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取 userService对象 使用getBean("");来获取容器中存在的对象
//在IOC容器中除了可以用bean的id来获取对象还可以使用bean的name属性来获取对象
//(1)可以通过bean的id属性值来获取IOC容器中的对象
UserService userService = (UserService) applicationContext.getBean("userService");
userService.addUser();
//(2)可以通过bean的name属性值来获取IOC容器中的对象
UserService name1 = (UserService) applicationContext.getBean("name1");
System.out.println("调用name1");
name1.addUser();
UserService name2 = (UserService) applicationContext.getBean("name2");
System.out.println("调用name2");
name2.addUser();
UserService name3 = (UserService) applicationContext.getBean("name3");
System.out.println("调用name3");
name3.addUser();
3.2通过构造方法注入
持久层
使用构造方法进行注入的时候Bean对象必须有一个带参的构造方法
public class UserServiceImpl implements UserService
private UserDao userDao;
//使用构造方法实现依赖注入
public UserServiceImpl(UserDao userDao)
this.userDao = userDao;
@Override
public void addUser()
userDao.InitUserDao();
System.out.println("UserService........addUser");
配置文件
使用构造方法进行注入的时候参数对象要使用 constructor-arg 一个constructor-arg注入一个参数
<!--通过 构造方法方法注入 (需要为注入的成员变量提供 Set 方法。)-->
<bean id="userDao2" class="com.xjx.dao.impl.UserDaoImpl"/>
<bean id="userService2" class="com.xjx.service.impl.UserServiceImpl">
<!--constructor-arg用来通过构造方法注入参数时使用,一个constructor-arg注入一个参数
构造方法中有几个需要注入的参数就需要几个constructor-arg
与构造方法中的参数进行匹配注入的时候使用name 或 index 或 type属性来进行指定参数注入-->
<!--name属性表示的是参数中要注入的参数名称(name:根据参数名称识别参数)-->
<constructor-arg name="userDao">
<ref bean="userDao2"/>
</constructor-arg>
<!--(index:根据参数位置识别参数)-->
<!--<constructor-arg index="0" ref="userDao2"/>-->
<!--(name:根据参数类型识别参数)-->
<!--<constructor-arg type="com.xjx.dao.UserDao" ref="userDao2"/>-->
</bean>
测试构造方法注入
public class UserServiceTest
public static void main(String[] args)
//启动IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取 userService对象 使用getBean("");来获取容器中存在的对象
UserService userService = (UserService) applicationContext.getBean("userService");
userService.addUser();
3.3自动注入
自动注入的方式有两种,一种是全局配置自动注入,另一种是局部配置自动注入。 无论全局配置或局部单独配置,都有 5 个值可以选择:no或byName或byType或 constructor或 default局部自动注入 : 通过 bean 标签中的 autowier 属性配置自动注入。有效范围:仅针对当前 bean 标签生效。 全局自动注入 :通过 beans 标签中的 default-autowire 属性配置自动注入。有效范围:配置文件中的所有 bean 标签都生效。 no:当 autowire 设置为 no 的时候,Spring 就不会进行自动注入。 byName:在 Spring 容器中查找 id 与(需要注入的bean)属性名相同的 bean,并进行注入。需要提供 set 方 法。 byType:在 Spring 容器中查找类型与属性名的类型相同的 bean,并进行注入。需要提供 set 方法。 constructor:仍旧是使用 byName 方式,只不过注入的时候,使用构造方式进行注入。 default:全局配置的 default 相当于 no,局部的 default 表示使用全局配置设置。
局部自动注入
通过 bean 标签中的 autowier 属性配置自动注入。<bean id="usersDaoMybatis" class="com.bjsxt.dao.impl.UsersDaoMybatisImpl"/>
<bean id="usersService" name="name1,name2,name3" class="com.bjsxt.service.impl.UsersServiceImpl" autowire="byType"> </bean>
全局自动注入(default-autowire="byName")
<?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"
default-autowire="byName">
4 依赖注入的数据类型
依赖注入的数据类型: 1.注入bean对象 2.注入基本数据类型和字符串 3.注入list集合 4.注入Set集合 5.注入Map集合 6.注入properties
业务层userServiceImp实现
所有的Bean对象都需要set方法
public class UserServiceImpl implements UserService
private UserDao userDao;
private String name;
private int age;
private List<String> list;
private Set<String> set;
private Set<Users> users;
private Map<String,String> map;
private Map<String,Users> mapUser;
private Properties properties;
//使用构造方法实现依赖注入
public UserServiceImpl(UserDao userDao)
this.userDao = userDao;
//使用set方法实现依赖注入
public void setUserDao(UserDao userDao)
this.userDao = userDao;
public void setName(String name)
this.name = name;
public void setAge(int age)
this.age = age;
public void setList(List<String> list)
this.list = list;
public void setSet(Set<String> set)
this.set = set;
public void setUsers(Set<Users> users)
this.users = users;
public void setMap(Map<String, String> map)
this.map = map;
public void setMapUser(Map<String, Users> mapUser)
this.mapUser = mapUser;
public void setProperties(Properties properties)
this.properties = properties;
@Override
public void addUser()
userDao.InitUserDao();
System.out.println("注入基本数据类型"+name+age);
System.out.println("注入list");
for (int i = 0 ; i <list.size(); i++)
System.out.println(list.get(i));
System.out.println("UserService........addUser");
配置文件
<!--
依赖注入的数据类型:
1.注入bean对象
2.注入基本数据类型和字符串
3.注入list集合
4.注入Set集合
5.注入Map集合
6.注入properties
-->
<bean id="userServiceData" class="com.xjx.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<!--注入的是基本数据类型或字符串的时候,注入的值不使用ref而是使用value来赋值-->
<property name="name" value="lance"/>
<property name="age" value="24"/>
<property name="list">
<list>
<value>javaSE</value>
<value>javaEE</value>
<!--如果list中注入的是IOC中的对象时不使用value而使用ref来向list中注入对象
例:向list中注入一个IOC容器中存在的id属性为userService对象
<ref>要注入的IOC中已经存在的对象id</ref>
如果list中注入的是IOC中不存在的对象时不使用value而使用bean创建对象来向list中注入对象
例:向list中注入一个UserDaoImpl对象(这个时候是可以不添加id属性的)
<bean class="com.xjx.dao.impl.UserDaoImpl"/>-->
</list>
</property>
<!--注入Set集合(Set集合为String类型)-->
<property name="set">
<set>
<value>lance</value>
<value>admin</value>
</set>
</property>
<!--注入Set集合(Set集合为引用数据类型Users对象)-->
<property name="users">
<set>
<bean class="com.xjx.pojo.Users">
<property name="name" value="admin"/>
<property name="age" value="18"/>
</bean>
</set>
</property>
<!--注入Map集合(Map集合value为String类型)-->
<property name="map">
<map>
<entry key="name" value="lance"/>
<entry key="age" value="24"/>
</map>
</property>
<!--注入Map集合(Map集合value为引用数据类型Users对象)-->
<property name="mapUser">
<map>
<entry key="user1" value-ref="user1"/><!--注入值是IOC容器中已经存在的对象-->
<entry key="user2"><!--注入的值不是IOC中存在的对象,需要用bean创建-->
<bean class="com.xjx.pojo.Users"/>
</entry>
</map>
</property>
<!--注入properties-->
<property name="properties">
<props>
<prop key="name">lance</prop>
<prop key="age">24</prop>
</props>
</property>
</bean>
<bean id="user1" class="com.xjx.pojo.Users"/>
<bean id="user2" class="com.xjx.pojo.Users"/>
测试依赖注入的数据类型:
/**依赖注入
* 在使用依赖注入时,如果注入的是 Bean 对象,
* 那么要求注入的 Bean 对象与被注入的 Bean 对象都需要 Spring IOC 容器来实例化。
* 注入方式:
* 1.使用set方式注入:需要为注入的成员变量提供 Set 方法。
* 2.使用构造方法注入:Bean 对象中需要提供有参的构造方法
*/
public class DependencyInjectionTest
public static void main(String[] args)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_dependency_injection.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceData");
userService.addUser();
Spring -- Spring配置文件详解(Bean实例化的三种方式IoC(控制反转) 与 DI(依赖注入)依赖注入详解)
01:Spring配置文件详解(Bean标签的基本配置(id,class)/ 范围配置 / 不同范围时的对象的创建时期 / Bean生命周期配置(生命周期方法) )
02: Spring配置文件详解(Bean实例化的三种方式、IoC(控制反转) 与 DI(依赖注入)、依赖注入详解)
03:Spring配置文件详解(Bean的依赖注入的数据类型(基本类型、引用类型、集合类型))
04: Spring配置文件详解(引入其他配置文件(分模块开发)、小结)
1. Bean实例化的三种方式
1.1 使用无参构造方法实例化(重点)
1.2 工厂静态方法实例化
1.3 工厂实例方法实例化
2. IoC(控制反转) 与 DI(依赖注入)
- 控制反转IOC(Inversion of Control),是一种设计思想,DI(Dependency Injection 依赖注入)是IoC的具体实现。
- 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
- 控制反转是一种通过描述(xml或注解)并通过第三方去生产或获取特定对象的方式。在spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)
- 所谓的IoC,一句话搞定 : 对象由Spring 来创建,管理,装配 !
3. 依赖注入详解
3.1 Bean的依赖注入入门
-
创建
UserDaoImpl
-
创建
UserService
,UserService
内部在调用UserDao
的save()
方法
-
将
UserServicelmpl
和UserDaoImpl
交给Spring Ioc容器管理
-
从Spring容器中获得UserService进行操作
-
分析
目前UserService
实例和UserDao
实例都存在与Spring
容器中,当前的做法是在容器外部获得UserService
实例和UserDao
实例,然后在程序中进行结合。
3.2 Bean的依赖注入分析
因为UserService
和UserDao
都在Spring
容器中,而最终程序直接使用的是UserService
,所以可以在Spring
容器中,将UserDao
设置到UserService
内部。
3.3 Bean的依赖注入
(Dependency Injection,DI
)概念
3.4 Bean的依赖注入方式(构造方法、set方法)
3.4.1 set方法注入
-
在UserServicelmpl中添加setUserDao方法
-
配置Spring容器调用set方法进行注入
-
测试代码
public static void main(String[] args) {
//解析beans.xml文件 , 生成管理相应的Bean对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//getBean : 参数即为spring配置文件中bean的id .
UserServiceImpl user = (UserServiceImpl) context.getBean("userService");
user.save();
}
- 测试结果:
3.4.2 set方法注入的另外一种方式:P命名空间注入
P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
- 首先,需要引入P命名空间:
- 修改注入方式
- 运行上面的测试代码:
3.4.3 构造方法注入
-
创建有参构造
-
配置Spring容器调用有参构造时进行注入
-
运行上面的测试代码:
以上是关于Spring详解-------依赖注入的三种方式实例详解的主要内容,如果未能解决你的问题,请参考以下文章