Spring-依赖注入(DI)相关
-
思考:
-
1.向一个类中传递数据的方式有几种?
- set方法
- 构造方法
-
2.依赖注入(DI)描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或者字符串呢?
- 引用类型
- 简单类型:基本数据类型和String
-
一、依赖注入的方式
setter注入 | 构造器注入 |
---|---|
简单类型 | 简单类型 |
引用类型 | 引用类型 |
1.1 setter注入 – 引用类型
-
(1)OrderDaoImpl类中,依赖UserDao和BookDao
/** * @author: sea * @date: 2023/6/25 15:25 */ public class OrderDaoImpl implements OrderDao { private UserDao userDao; private BookDao bookDao; @Override public void save() { System.out.println("Order saving ... "); userDao.save(); bookDao.save(); } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } }
-
(2)配置文件中配置bean和各个bean之间的依赖关系注入**【property标签的ref属性注入】**
<bean id="userDao" class="com.sea.dao.impl.UserDaoImpl"/> <bean id="bookDao" class="com.sea.dao.impl.BookDaoImpl"/> <bean id="orderDao" class="com.sea.dao.impl.OrderDaoImpl"> <property name="userDao" ref="userDao" /> <property name="bookDao" ref="bookDao" /> </bean>
-
(3)获取Spring容器中管理的bean,并调用相关方法
/** * @author: sea * @date: 2023/6/30 15:37 */ public class AppForDISetter { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); OrderDao orderDao = (OrderDao) context.getBean("orderDao"); orderDao.save(); } }
1.2 setter注入 – 简单类型
-
(1)UserDaoImpl类中,依赖两个简单类型:int和String
/** * @author: sea * @date: 2023/6/25 15:26 */ public class UserDaoImpl implements UserDao { private int id; private String name; @Override public void save() { System.out.println("UserDao saving ... "); System.out.println("==== " + this.id + " ==== " + this.name); } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } }
-
(2)配置文件中配置bean和简单类型注入**【property标签的value属性注入】**
<bean id="userDao" class="com.sea.dao.impl.UserDaoImpl"> <property name="id" value="1"/> <property name="name" value="sea"/> </bean>
-
(3)获取Spring容器中管理的bean,并调用相关方法
/** * @author: sea * @date: 2023/6/30 15:37 */ public class AppForDISetter { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (userDao) context.getBean("userDao"); userDao.save(); } }
1.3 构造器注入
-
(1)BookDaoImpl类和UserDaoImpl类,其中UserDaoImpl依赖两个简单类型:int和String
/** * @author: sea * @date: 2023/6/25 15:25 */ public class BookDaoImpl implements BookDao { private BookDaoImpl() {//此处私有的构造方法也可以找到【反射机制】 } public void save() { System.out.println("Bookdao saving ... "); } }
/** * @author: sea * @date: 2023/6/25 15:26 */ public class UserDaoImpl implements UserDao { private int id; private String name; public UserDaoImpl(int id, String name) { this.id = id; this.name = name; } @Override public void save() { System.out.println("UserDao saving ... "); System.out.println("==== " + this.id + " ==== " + this.name); } }
-
(2)BookServiceImpl类,该类依赖BookDao和UserDao两个Dao类,并**【通过构造器进行注入】**
/** * @author: sea * @date: 2023/6/30 16:12 */ public class BookServiceImpl implements BookService { BookDao bookDao; UserDao userDao; public BookServiceImpl(BookDao bookDao, UserDao userDao) { this.bookDao = bookDao; this.userDao = userDao; } @Override public void save() { System.out.println("bookService saving ..."); bookDao.save(); userDao.save(); } }
-
(3)配置文件中配置bean,以及相关的依赖注入**【通过
constructor-arg
标签进行注入】**<bean id="bookDao" class="com.sea.dao.impl.BookDaoImpl"/> <bean id="userDao" class="com.sea.dao.impl.UserDaoImpl"> <constructor-arg name="id" value="1"/> <constructor-arg name="name" value="sea"/> </bean> <bean id="bookService" class="com.sea.service.impl.BookServiceImpl"> <constructor-arg name="bookDao" ref="bookDao"/> <constructor-arg name="userDao" ref="userDao"/> </bean>
-
(4)获取Spring容器中管理的bean,并调用相关方法
/** * @author: sea * @date: 2023/6/30 15:37 */ public class AppForConstructor { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); BookService bookService = (BookService) context.getBean("bookService"); bookService.save(); } }
1.4 两种注入方式选择
- 使用构造器方式注入:
- 1.强制依赖
- 2.Spring框架建议使用构造器,比较严谨
- 使用setter方式注入:
- 1.可选依赖
- 2.自己开发的模块推荐setter注入
- 【可能管理的类没有提供构造器,因此,根据实际开发情况选择!】
- 目前存在的弊端:还是得自己手动配置!!因此,引入自动装配的概念!
二、依赖自动装配
2.1 概念
- **IoC容器 **根据bean所依赖的资源在容器中 **自动查找并注入 **到bean中的过程称为 自动装配。
2.2 自动装配的方式
- 按类型(常用)
- 按名称
- 按构造方法
- 不启用自动装配
2.3 实现
-
在配置文件中,使用bean标签的
autowire
设置自动装配的方式; -
其中:
- 自动装配仅适用于引用类型装配;
- 按类型装配:需要保证相同类型的bean只能有一个;
- 按名称装配:需要保证bean的
id
属性与变量名一致,即变量名称与配置产生耦合,不推荐使用; - 自动装配优先级低于setter注入与构造器注入,同时使用时,自动装配配置失效。
三、集合注入
-
集合:
- 数组
- List
- Set
- Map
- Properties
-
注入方式:
<?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"> <bean id="bookDao" class="com.sea.dao.impl.BookDaoImpl"> <property name="arr"> <array> <value>1</value> <value>2</value> <value>3</value> <value>4</value> <value>5</value> </array> </property> <property name="list"> <list> <value>a</value> <value>b</value> <value>c</value> <value>d</value> <value>e</value> </list> </property> <property name="map"> <map> <entry key="1" value="a"/> <entry key="2" value="b"/> <entry key="3" value="c"/> <entry key="4" value="d"/> <entry key="5" value="e"/> </map> </property> <property name="set"> <set> <value>a</value> <value>b</value> <value>c</value> <value>d</value> <value>e</value> </set> </property> <property name="properties"> <props> <prop key="driver">com.mysql.jdbc.Driver</prop> <prop key="url">jdbc:mysql://localhost:3306/test</prop> <prop key="username">root</prop> <prop key="password">123456</prop> </props> </property> </bean> <bean id="bookService" class="com.sea.service.impl.BookServiceImpl"> <constructor-arg name="bookDao" ref="bookDao"/> </bean> </beans>
- 注入的值可以是基本数据类型,也可以是引用类型。
四、案例:数据源对象管理
-
以配置数据库连接池为例:
<!-- druid连接池 --> <bean id="dataSource_druid" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/springdb"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!-- c3p0连接池 --> <bean id="dataSource_c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springdb"/> <property name="user" value="root"/> <property name="password" value="123456"/> <property name="maxPoolSize" value="1000"/> </bean>
-
如果需要从配置文件中读取配置:
- 1.开启一个新的命名空间
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > ...... </beans>
- 2.使用context空间加载properties文件
- 3.使用属性占位符 ${} 读取properties文件中的值
<!-- 1.开启contex命名空间 --> <!-- 2.使用context空间加载properties文件 --> <context:property-placeholder location="mysql.properties"/> <!-- 3.使用属性占位符 ${} 读取properties文件中的值 --> <!-- druid连接池 --> <bean id="dataSource_druid" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${user}"/> <property name="password" value="${password}"/> </bean>
-
mysql.properties
配置文件如下:driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/springdb username=root password=123456
-
此处
username
可能会与系统的环境变量冲突,系统的环境变量优先级高,因此可能输出的username不是配置文件中的值。解决:<!-- 增加属性 system-properties-mode="NEVER" 即可 --> <!-- 2.使用context空间加载properties文件 --> <context:property-placeholder location="mysql.properties" system-properties-mode="NEVER"/>
-
要读取多个配置文件:
- 读取当前工程目录下所有的properties文件。【标准格式】
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
- 读取当前工程目录下所有的properties文件以及依赖的外部jar包中的properties文件。
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
-