一、IOC
1. 什么是IOC
- 控制反转,把对象创建核对对象之间的调用过程,交给Spring进行管理
2. IOC的目的
- 为了耦合度降低
3. IOC的底层原理
- xml解析
- 工厂模式
- 反射
4. IOC过程
- 创建xml配置文件,配置创建的对象
<bean id="user" class="com.github.entity.User" > </bean>
- 创建工厂类
class UserFactory{
public static User getUser(){
String class = class的属性值 // xml解析获得类的名称
Class clazz = Class.forName(class); //通过反射创建对象
return (User)clazz.newInstance();
}
}
5. BeanFactory接口
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
- Spring提供IOC容器实现的俩种方式——两个接口
- BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
加载配置文件时候不会创建对象,在获取对象使用才去创建对象- ApplicationContext:BeanFactory的子接口,提供更多更强大的功能,一般由开发人员进行使用
加载配置文件时候就会把配置文件的对象进行创建- ApplicationContext接口有实现类
二、IOC操作Bean管理
1. 什么是Bean管理
- Spring创建对象
- Spring注入属性
2. Bean管理的两种操作方式
- 基于xml配置方式实现
- 基于注解方式实现
3. 基于XML方式
3.1 创建对象
- 首先创建一个User类
public class User {
private String name;
private Integer age;
private String gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public User(String name, Integer age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public User(){
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
public void add(){
System.out.println("hello");
}
}
- 配置xml文件
<bean id="user" class="com.github.entity.User"></bean>
- 在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
- 在bean标签里有很多属性,下面是常用的属性
- id属性:唯一标识
- class属性:类全路径
- name属性:也是标识,里面可以存在特殊字符
- scope属性:确定是否为单例对象
3.2 注入属性
- DI:依赖注入,就是注入属性
3.2.1 set 方式注入
- 配置xml文件
<!-- set注入属性 -->
<bean id="user" class="com.github.entity.User">
<!-- 使用property完成属性注入
name: 类里面属性名称
value:向属性注入的值
-->
<property name="name" value="zhangsan"></property>
<property name="age" value="15"></property>
<property name="gender" value="男"></property>
</bean>
3.2.2 使用有参构造进行注入
- 配置xml文件
<bean id="user1" class="com.github.entity.User">
<constructor-arg name="name" value="wu"></constructor-arg>
<constructor-arg name="age" value="16"></constructor-arg>
<constructor-arg name="gender" value="女"></constructor-arg>
</bean>
3.2.3 p名称空间注入
- 使用p名称空间注入,可以简化基于xml的配置方式
- 添加p名称空间在配置文件中
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- 配置xml文件
<bean id="user2" class="com.github.entity.User" p:name="李四" p:age="21" p:gender="男"> </bean>
3.2.4 注入字面量
- 扩展User类
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
- NuLL值
<bean id="user3" class="com.github.entity.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="15"></property>
<property name="gender" value="男"></property>
<property name="address">
<null></null>
</property>
</bean>
- 属性中包含特殊符号
<bean id="user4" class="com.github.entity.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="15"></property>
<property name="gender" value="男"></property>
<property name="address">
<value><![CDATA[<<西安>>]]></value>
</property>
</bean>
- 测试类结果
3.2.5 注入属性-外部bean
- 创建两个类
public class Dept {
private String dname;
public Dept() {
}
public void setDname(String dname) {
this.dname = dname;
}
}
public class Emp {
private String name;
private Integer age;
private Dept dept;
public Emp() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", age=" + age +
", dept=" + dept +
'}';
}
}
xml配置文件
<bean id="emp" class="com.github.entity.Emp">
<property name="name" value="zhangsan"></property>
<property name="age" value="20"></property>
//级联的一种
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.github.entity.Dept">
<property name="dname" value="研发"></property>
</bean>
3.2.6 注入属性-内部bean
- xml配置
<bean id="emp" class="com.github.entity.Emp">
<property name="name" value="zhangsan"></property>
<property name="age" value="20"></property>
<property name="dept">
<bean id="dept" class="com.github.entity.Dept">
<property name="dname" value="研发"></property>
</bean>
</property>
</bean>
3.2.7 注入属性-级联赋值
- 级联赋值需要getter方法
public Dept getDept() {
return dept;
}
- xml配置文件
<bean id="emp" class="com.github.entity.Emp">
<property name="name" value="zhangsan"></property>
<property name="age" value="20"></property>
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="技术部"></property>
</bean>
<bean id="dept" class="com.github.entity.Dept">
</bean>
3.2.8 注入集合属性
- 注入数组类型属性
- 注入List集合类型属性
- 注入Set集合类型属性
- 注入Map集合类型属性
package com.github.entity;
import java.awt.*;
import java.util.*;
import java.util.List;
public class CollcetionSum {
private String[] string;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
public void setString(String[] string) {
this.string = string;
}
public void setList(List list) {
this.list = list;
}
public void setSet(Set set) {
this.set = set;
}
public void setMap(Map map) {
this.map = map;
}
@Override
public String toString() {
return "CollcetionSum{" +
"string=" + Arrays.toString(string) +
", list=" + list +
", set=" + set +
", map=" + map +
'}';
}
}
<bean id="collectSum" class="com.github.entity.CollcetionSum">
<property name="string">
<array>
<value>语文</value>
<value>数学</value>
</array>
</property>
<property name="list">
<list>
<value>张安</value>
<value>李四</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"></entry>
<entry key="key2" value="value2"></entry>
</map>
</property>
<property name="set">
<set>
<value>123</value>
<value>456</value>
</set>
</property>
</bean>
</beans>
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans4.xml");
CollcetionSum collcetionSum = context.getBean("collectSum",CollcetionSum.class);
System.out.println(collcetionSum);
}
- 集合里面设置对象类型值
<bean id="dept" class="com.github.entity.Dept">
<property name="dname" value="研发"></property>
</bean>
<bean id="listClass" class="com.github.entity.ListClass">
<property name="list">
<list>
<ref bean="dept"></ref>
</list>
</property>
</bean>
- 把集合注入部分提取出来
- 添加名称util空间
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
- 配置xml文件
<bean id="dept" class="com.github.entity.Dept">
<property name="dname" value="研发"></property>
</bean>
<util:list id="deptlist">
<ref bean="dept"></ref>
</util:list>
<bean id="listClass" class="com.github.entity.ListClass">
<property name="list" ref="deptlist"></property>
</bean>
3.3 FactoryBean
- Spring有俩种类型bean,一种为普通bean,另一种为工厂bean(FactoryBean)
- 普通bean:在配置文件中定义bean类型就是返回类型
- 工厂bean:在配置文件中定义bean类型可以和返回类型不一样
3.3.1 如何实现
- 创建类,让这个类作为工厂bean,实现接口FactoryBean
- 实现接口里面的方法,在实现的方法中定义返回的bean类型
- 创建类
public class MyBean implements FactoryBean<Dept> {
@Override
public Dept getObject() throws Exception {
Dept dept = new Dept();
dept.setDname("145");
return dept;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
- 配置xml
<bean id="mybean" class="com.github.entity.MyBean"> </bean>
- 编写测试类
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Dept dept = context.getBean("mybean",Dept.class);
System.out.println(dept);
}
4.xml自动装配
4.1 什么是自动装配
- 根据指定装配规则,Spring自动将匹配的属性值进行注入
4.2 自动装配过程
- bean标签的autowire属性,配置自动装配
1.byName:根据属性名称注入
2. byType:根据属性类型注入
- xml配置文件
<bean id="emp" class="com.github.entity.Emp" autowire="byType">
</bean>
<bean id="dept" class="com.github.entity.Dept">
</bean>
<bean id="emp" class="com.github.entity.Emp" autowire="byName">
</bean>
<bean id="dept" class="com.github.entity.Dept">
</bean>
5.引入外部资源文件
- 引入context名称空间
- 配置文件
<context:property-placeholder location="classpath:djbc.properties"></context:property-placeholder>