Spring学习(二)-IOC容器
一、IOC && DI介绍
1.1、简介
1)IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
2)DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接
1.2、IOC底层使用原理
1)XML解析技术
2)工厂方法
3)反射
二、IOC容器
2.1、BeanFactory
在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
Spring 提供了两种类型的 IOC 容器实现.
1)BeanFactory: IOC 容器的基本实现.
2)ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.
3)BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
4)无论使用何种方式, 配置文件时相同的
2.2、ApplicationContext
ApplicationContext 的主要实现类:
1)ClassPathXmlApplicationContext:从 类路径下加载配置文件
2)FileSystemXmlApplicationContext: 从文件系统中加载配置文件
ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean
三、Bean管理(基于XML)
3.1、基于XML创建对象
<!--配置User对象--> <bean id="user" class="com.dianchou.spring.User"></bean>
1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
2)在 bean 标签有很多属性,介绍常用的属性
- id 属性:唯一标识
- class 属性:类全路径(包类路径)
3)创建对象时候,默认也是执行无参数构造方法完成对象创建
3.2、基于XML注入属性
3.2.1、使用 set 方法进行注入
1)创建类,定义属性和对应的 set 方法
package com.dianchou.spring; /** * @author lawrence * @create 2020-07-07 11:55 */ public class Book { private String name; private String author; public void setName(String name) { this.name = name; } public void setAuthor(String author) { this.author = author; } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", author='" + author + '\'' + '}'; } }
2)在 spring 配置文件配置对象创建,配置属性注入
<!--配置Book对象--> <bean id="book" class="com.dianchou.spring.Book"> <!--使用 property 完成属性注入 name:类里面属性名称 value:向属性注入的值 --> <property name="name" value="红楼梦"></property> <property name="author" value="曹雪芹"></property> </bean>
3)测试
@Test public void testBook(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml"); Book book = ctx.getBean("book", Book.class); System.out.println(book); }
3.2.2、使用有参数构造进行注入
1)创建类,定义属性,创建属性对应有参数构造方法
package com.dianchou.spring; /** * @author lawrence * @create 2020-07-07 14:06 */ public class Order { private String name; private String address; public Order() { } public Order(String name, String address) { this.name = name; this.address = address; } @Override public String toString() { return "Order{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}'; } }
2)在 spring 配置文件中进行配置
<!-- 配置Order对象 --> <bean id="order" class="com.dianchou.spring.Order"> <constructor-arg name="name" value="电脑"></constructor-arg> <constructor-arg name="address" value="深圳"></constructor-arg> </bean>
@Test public void testOrder(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml"); Order order = ctx.getBean("order", Order.class); System.out.println(order); }
3.2.3、p名称空间注入
使用 p 名称空间注入,可以简化基于 xml 配置方式
1)在配置文件中添加p名称空间
2)在配置文件中进行属性注入
<bean id="book" class="com.dianchou.spring.Book" p:name="AAA" p:author="BBB"></bean>
3.2.4、字面量注入
1)null值注入
<!--配置Book对象--> <bean id="book" class="com.dianchou.spring.Book"> <property name="name" value="红楼梦"></property> <property name="author"> <null/> </property> </bean>
2)特殊符号注入
<!--配置Book对象--> <bean id="book" class="com.dianchou.spring.Book"> <!--属性值包含特殊符号 1 把<>进行转义 < > 2 把带特殊符号内容写到 CDATA --> <property name="name"> <value><![CDATA[<<红楼梦>>]]></value> </property> <property name="author" value="曹雪芹"></property> </bean>
3.2.5、外部bean注入
1)创建UserService类和UserDao接口及接口的实现类
UserDao接口:
package com.dianchou.spring.dao; /** * @author lawrence * @create 2020-07-07 14:41 */ public interface UserDao { public void add(); }
UserDaoImpl实现类:
package com.dianchou.spring.dao; /** * @author lawrence * @create 2020-07-07 14:42 */ public class UserDaoImpl implements UserDao{ @Override public void add() { System.out.println("UserDaoImpl add...."); } }
UserService:
package com.dianchou.spring.service; import com.dianchou.spring.dao.UserDao; /** * @author lawrence * @create 2020-07-07 14:42 */ public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add(){ System.out.println("UserService add..."); userDao.add(); } }
2)spring配置文件中配置
<!-- 注入userDaoImpl --> <bean id="userDaoImpl" class="com.dianchou.spring.dao.UserDaoImpl"></bean> <!--注入UserService--> <bean id="userService" class="com.dianchou.spring.service.UserService"> <!--注入 userDao 对象 name 属性:类里面属性名称 ref 属性:创建 userDao 对象 bean 标签 id 值 --> <property name="userDao" ref="userDaoImpl"></property> </bean>
3)测试
@Test public void testUserService(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = ctx.getBean("userService", UserService.class); System.out.println(userService); userService.add(); }
3.2.6、内部bean注入
一对多关系:部门和员工 ,在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
1)创建部门和员工类
部门类:
package com.dianchou.spring.dao; /** * @author lawrence * @create 2020-07-07 15:00 */ public class Department { private String departmentName; public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } @Override public String toString() { return "Department{" + "departmentName='" + departmentName + '\'' + '}'; } }
员工类:
package com.dianchou.spring.dao; /** * @author lawrence * @create 2020-07-07 15:01 */ public class Employee { private String name; private String gender; //员工属于某一个部门,使用对象形式表示 private Department department; public void setName(String name) { this.name = name; } public void setGender(String gender) { this.gender = gender; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", gender='" + gender + '\'' + ", department=" + department + '}'; } }
2)spring配置文件
<bean id="employee" class="com.dianchou.spring.dao.Employee"> <!--配置普通属性--> <property name="name" value="lawrence"></property> <property name="gender" value="男"></property> <!--配置对象属性--> <property name="department"> <bean id="department" class="com.dianchou.spring.dao.Department"> <property name="departmentName" value="研发部"></property> </bean> </property> </bean>
3)测试
@Test public void testEmployee() { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml"); Employee employee = ctx.getBean("employee", Employee.class); System.out.println(employee); }
3.2.7、级联赋值
1)方式一
<bean id="employee" class="com.dianchou.spring.dao.Employee"> <!--配置普通属性--> <property name="name" value="lawrence"></property> <property name="gender" value="男"></property> <!--配置对象属性--> <property name="department" ref="department"></property> </bean> <bean id="department" class="com.dianchou.spring.dao.Department"> <property name="departmentName" value="研发部"></property> </bean>
2)方式二
<bean id="employee" class="com.dianchou.spring.dao.Employee"> <!--配置普通属性--> <property name="name" value="lawrence"></property> <property name="gender" value="男"></property> <!--配置对象属性--> <property name="department" ref="department"></property> <property name="department.departmentName" value="开发部"></property> </bean> <bean id="department" class="com.dianchou.spring.dao.Department"></bean>
3.2.8、注入数组,List,Map,Set类型属性
1)创建实体类
package com.dianchou.spring.dao; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; /** * @author lawrence * @create 2020-07-07 15:32 */ public class Student { //1 数组类型属性 private String[] courses; //2 list 集合类型属性 private List<String> list; //3 map 集合类型属性 private Map<String,String> maps; //4 set 集合类型属性 private Set<String> sets; public void setSets(Set<String> sets) { this.sets = sets; } public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMaps(Map<String, String> maps) { this.maps = maps; } @Override public String toString() { return "Student{" + "courses=" + Arrays.toString(courses) + ", list=" + list + ", maps=" + maps + ", sets=" + sets + '}'; } }
2)spring配置文件配置
<bean id="student" class="com.dianchou.spring.dao.Student"> <!--数组类型属性注入--> <property name="courses"> <array> <value>语文</value> <value>数学</value> </array> </property> <!--List集合类型注入--> <property name="list"> <list> <value>AAA</value> <value>BBB</value> </list> </property> <!--map类型注入--> <property name="maps"> <map> <entry key="JAVA" value="java"></entry> <entry key="PYTHON" value="python"></entry> </map> </property> <!--set类型注入--> <property name="sets"> <set> <value>MySQL</value> <value>Redis</value> </set> </property> </bean>
3)测试
@Test public void testStudent(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("bean2.xml"); Student student = ctx.getBean("student", Student.class); System.out.println(student); }
相关细节:
①在集合里面设置对象类型值
<!--创建多个 course 对象--> <bean id="course1" class="com.dianchou.spring.dao.Course"> <property name="name" value="Spring"></property> </bean> <bean id="course2" class="com.dianchou.spring.dao.Course"> <property name="name" value="MyBatis"></property> </bean> <!--注入 list 集合类型,值是对象--> <bean id="courseList" class="com.dianchou.spring.dao.CourseList"> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>
②把集合注入部分提取出来
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!