1. 什么是IOC
- IOC是控制反转,可以把对象创建和对象之间的调用交给Spring进行管理
- 使用IOC的目的:降低耦合度
2. IOC的底层原理
xml解析、工厂模式、反射
画图讲解IOC的原理

3. IOC接口
3.1 IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
3.2 Spring提供IOC容器的两种方式
BeanFactory:IOC容器的基本实现,是Spring内部使用的容器,一般不提供开发人员
加载配置文件的时候不会创建对象,在获取对象(使用时才创建)

ApplicationContext:是BeanFactory接口的子接口,提供更多更强大的功能,提供给开发人员
加载配置文件的时候就会把配置文件对象进行创建
ClassPathApplication是ApplicationContext的主要实现类

4. IOC操作Bean管理
- Bean管理值两个操作
- Spring创建对象
- Spring注入属性
5. 基于XML配置文件方式实现Bean管理
5.1 创建对象

- 在spring配置文件中配置bean标签,在标签中加入属性
- 常用的属性: (1)id-唯一标识 (2)class-全限定名
- 创建对象时,默认执行无参构造器
5.2基于xml方式的注入属性
DI:依赖注入 注入属性
- set方法注入 ---类中创建属性的set方法
- 有参构造器注入 ---类中创建带属性的构造方法


- p命名空间注入(了解) 命名空间添加如下图


5.3 xml设置其他类型属性
1.字面量--基础类型+String类+null
(1)null
<property name="name" > <null/> </property>
(2)包含特殊符号
解决方法
a.使用转义(用的少)
b.CDATA
<property name="name" >
<value>
<![CDATA[<<什么鬼>>]]>
</value>
</property>
2.外部Bean 创建一个Book类,在user类中创建一个Book的属性

3.内部Bean和级联赋值
一个用户可以有多本书,将user类的中book删除,在Book类中添加User属性


5.4 集合类型属性注入
1.集合属性注入入门
先定义一个类
import lombok.Data;
import lombok.ToString;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@ToString
public class Stu {
private String[] courses;
private List<String> list;
private Map<String,String> map;
private Set<String> set;
}
配置文件
<bean id="stu" class="com.bin.spring5.collection.Stu">
<property name="courses">
<array>
<value>数学</value>
<value>语文</value>
</array>
</property>
<property name="list">
<list>
<value>小斌</value>
<value>大斌</value>
</list>
</property>
<property name="map">
<map>
<entry key="java" value="java"></entry>
<entry key="php" value="最好的语言"></entry>
</map>
</property>
<property name="set">
<set>
<value>吃饭</value>
<value>喝酒</value>
</set>
</property>
</bean>
2.集合中存入对象
创建一个course类
package com.bin.spring5.collection;
import lombok.Data;
@Data
public class Course {
private String name;
}
在stu类中加入新的属性
private List<Course> courseList;
配置文件中添加
<bean id="course1" class="com.bin.spring5.collection.Course">
<property name="name" value="python"></property>
</bean>
<bean id="course2" class="com.bin.spring5.collection.Course">
<property name="name" value="redis"></property>
</bean>
在stu的bean中添加
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
3.把集合注入部分提取出来
现在XML文件中引入一个util的命名空间
<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: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">
配置文件如此设置
<bean id="stu2" class="com.bin.spring5.collection.Stu">
<property name="list" ref="list"></property>
</bean>
<util:list id="list">
<value>数学</value>
<value>语文</value>
</util:list>
5.5 IOC中的FactoryBean
Spring中有两种类型的bean,一种普通bean,一种工厂bean(FactoryBean)
-
普通bean:在配置文件中定义bean的类型就是返回类型
-
工厂bean:在配置文件定义bean类型可以和返回类型不一样
第一步:创建一个类,让泪作为工厂bean,实现接口FactoryBean。
第二步: 实现接口里的方法,实现方法中定义返回bean的类型。
写一个类实现接口,注意接口的泛型就是返回Bean的类型
import com.bin.spring5.Book;
import org.springframework.beans.factory.FactoryBean;
public class BookFac implements FactoryBean<Book> {
//定义返回的bean
@Override
public Book getObject() throws Exception {
Book book = new Book();
book.setBookName("java从入门到如土");
return book ;
}
@Override
public Class<?> getObjectType() {
return null;
}
}
配置文件中加入
<bean id="bookFac" class="com.bin.spring5.factoryBean.BookFac"></bean>
测试方法
public void factoryBean(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("application.xml");
Book book = (Book) applicationContext.getBean("bookFac");
System.out.println(book);
}
5.6 IOC中bean的作用域
在spring中可以设置设置bean时单例还是多例的,默认是单例的singleton
如果需要是多例的,在bean标签里面设置一个属性scope="prototype"
singleton和prototype的区别
- singleton单实例,prototype多实例
- scope是singleton时,在加载Spring文件时创建对象;scope是prototype时,在调用getBean方法时创建多实例对象。
另外还有request和session 和global-session三种
5.7 IOC的bean的生命周期
生命周期:对象从创建到对象销毁的过程
5.7.1 bean的生命周期-基础版
- 通过构造器出创建bean实例(无参构造器)
- 为bean的属性设置值和其他bean引用(set方法)
- 调用bean的初始化方法(需要进行配置)
- bean可以使用(对象获取到了)
- 当容器关闭时候,掉哦越难过bean的销毁方法(需要进行配置销毁方法)
创建一个类来体现生命周期
public class Orders {
public Orders() {
System.out.println("调用无参构造器");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用set方法设置值");
this.name = name;
}
//创建一个执行的初始化方法
public void init(){
System.out.println("初始化方法");
}
//创建一个销毁的方法
public void destroy(){
System.out.println("销毁的方法");
}
private String name;
}
配置文件
<bean id="orders" class="com.bin.spring5.bean.Orders" init-method="init" destroy-method="destroy">
<property name="name" value="huaweiphone"></property>
</bean>
测试方法
public void beanLife(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("application.xml");
Orders orders = (Orders) applicationContext.getBean("orders");
System.out.println(orders);
System.out.println("使用了orders");
((ClassPathXmlApplicationContext)applicationContext).close();
}

5.7.2 后置处理器
- 通过构造器出创建bean实例(无参构造器)
- 为bean的属性设置值和其他bean引用(set方法)
- 把bean的实例传递给后置处理的postProcessBeforeInitialization方法
- 调用bean的初始化方法(需要进行配置)
- 把bean的实例传递给后置处理的postProcessAfterInitialization方法
- 当容器关闭时候,掉哦越难过bean的销毁方法(需要进行配置销毁方法)
演示后置处理器 创建一个类去实现后置处理器
//后置处理器
public class PostProcess implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之后执行的方法");
return bean;
}
}
在配置文件中配置后置处理器,之后所有的对象生成都会执行后置处理器
<!--配置后置处理器-->
<bean id="postProcess" class="com.bin.spring5.bean.PostProcess" ></bean>
执行测试方法 结果如下

5.8 基于xml的自动装配
根据指定的装配规则(属性名称或者属性类型),Spring自动将匹配的属性进行注入
创建两个类
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Emp {
private Dept dept;
}
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Emp {
private Dept dept;
}
配置文件
<!--测试自动装配-->
<bean id="emp" class="com.bin.spring5.Autowire.Emp" autowire="byType"></bean>
<bean id="dept" class="com.bin.spring5.Autowire.Dept">
<property name="name" value="xiaobin"></property>
</bean>
自动装配在配置bean标签中使用autowird配置自动装配,该属性有两个常用的值
- byType,根据属性类型注入
- byName,根据属性名称注入,注入bean的id和类属性名称一样
5.9 外部属性文件
创建一个外部properties文件
prop.driverClass=com.mysql.jdbc.Driver
prop.username=root
prop.password=root
prop.url=jdbc:mysql:///db
引入名称空间
<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:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
在配置文件中使用标签引入外部文件
<!--驱动名称-原方式-->
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="url" value="jdbc:mysql:///db"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!-- 引入外部文件 -->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password}"></property>
<property name="url" value="${prop.url}"></property>
<property name="driverClassName" value="${prop.driverClass}"></property>
</bean>
6. 基于注解的方式实现
6.1 什么是注解
- 注解是代码的一种特殊标记,格式:@注解名称(属性=属性值,属性=属性值)
- 注解可以在写在类上,方法上,属性上
- 使用注解的目的,简化XML配置
6.2 SPring针对Bean管理中创建对象提供的注解
- @compoment
- @Controller
- @Service
- @Repository 上述4个注解功能一样,在类上创建Bean实例
1.需要先导入一个AOP的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
2.开启注解扫描 在配置文件中添加
<context:component-scan base-package="com.bin.spring"></context:component-scan>
3.创建类并使用注解 默认的对象名称是类名首字母小写
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
}
4.测试代码
@org.junit.Test
public void anno(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("application.xml");
MyComponent myComponent = applicationContext.getBean("myComponent", MyComponent.class);
System.out.println(myComponent);
}
6.3 基于注解方式实现属性注入
- @Autowired:根据属性类型注入
- @Qualifier:根据属性名称注入
- @Resource:可以根据类型注入,也可以根据名称注入
- @Value:注入普通属性类型
6.3.1 @Autowired
@Repository
public class MyDao {
public void a(){
System.out.println("dao执行了A方法");
}
}
@Service
public class MyService {
@Autowired
private MyDao dao;
public void b(){
System.out.println("执行了b方法");
dao.a();
}
}
测试方法
@org.junit.Test
public void anno2(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("application.xml");
MyService myService = applicationContext.getBean("myService", MyService.class);
System.out.println(myService);
myService.b();
}
6.3.2 @Qualifier
@Repository("dao")
public class MyDao {
public void a(){
System.out.println("dao执行了A方法");
}
}
@Service
public class MyService {
@Qualifier("dao ")
@Autowired
private MyDao dao;
public void b(){
System.out.println("执行了b方法");
dao.a();
}
}
测试方法同上
6.3.3 @Resource
// @Resource //根据类型注入
@Resource(name ="dao") //根据名称注入
private MyDao dao;
6.3.4 @Value
@Value("name")
private String name;
6.4 纯注解开发
纯注解开发的话 这个也不能要
<context:component-scan base-package="com.bin.spring"></context:component-scan>
所以我们需要使用java配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration//声明是一个配置类
@ComponentScan(basePackages = "com.bin.spring5")//需要扫的包
public class SpringConfig {
}
测试类
@org.junit.Test
public void anno3(){
ApplicationContext applicationContext =new AnnotationConfigApplicationContext(SpringConfig.class);
MyService myService = applicationContext.getBean("myService", MyService.class);
System.out.println(myService);
myService.b();
}