day2 Spring IOC
IOC ,即控制翻转,把对象的创建和对象间的调用过程,都交给spring进行管理。
一、IOC底层逻辑
- xml解析
- 工厂模式
- 反射
工厂模式
在一个类调用另一个类时,为了降低耦合度,使用工厂设计模式来实现。
class UserService{
execute(){
UserDao user = UserFactory.getUser();
user.add();
}
}
class UserDao{
add(){
...
}
}
class UserFactory{
public static UserDao getUser(){
return new UserDao();
}
}
xml 解析
解析xml文件
反射
获取类的字节码文件
Class.forName();
IOC 过程
<bean id="dao" class="com.springTest.dao.User"></bean>
class UserFactory{
public static UserDao getUser(){
// classValue 由 xml 解析获取
String classValue = classValue;
// 通过反射获取对象
Class claxx = Class.forName(classValue);
// 通过反射对象来创建对象并返回
return (User)claxx.newInstance();
}
}
二、IOC (接口)
IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
spring 实现IOC容器
两种方式
- BeanFactory:IOC容器的基本实现,内部使用,不提供给开发人员使用。
- ApplicationContext:BeanFactory 接口的子接口,提供更多的功能,给开发人员使用。
BeanFactory 在加载配置文件时,不会创建对象,在获取对象时才会去创建。
ApplicatonContext 在加载配置文件时,就会创建对象。
关于 ApplicationContext 的主要实现类
- FileSystemXMLApplicationContext:通过
本地磁盘地址路径
来获取xml文件 - ClassPathXmlApplicationContext:通过
项目默认资源路径+具体路径
来获取xml文件
三、IOC 操作(bean管理)
什么是bean管理
- spring 创建对象
- spring 属性注入(在创建对象时,向对象的属性设置值)
Bean 管理操作的两种方式
-
基于 xml 配置文件实现
-
基于 xml 方式创建对象
<bean></bean> id : 唯一标识 class : 要创建对象,类的全路径
- 使用 bean 标签,通过在标签里添加对应属性,可以实现对象的创建
- 创建对象时,默认使用无参构造方法进行创建。
-
基于 xml 方式注入属性
DI:依赖注入,即注入属性(DI 就是依赖注入的具体实现,要在对象创建完成的情况下进行)
(1)第一种方法:set方法注入
<bean id="book" class="com.edu.dao.User"> <!-- name为属性名,value为对应值 --> <property name="name" value="zs"><property> </bean>
(2)第二种方法:有参构造注入
<bean id="book" class="com.edu.dao.User"> <!-- 对应构造方法,name为形参,value为值 --> <constructor-arg name="name" value="zs"><constructor-arg> </bean>
外部 bean 注入
内部 bean 与 级联赋值
xml 注入集合类型属性值
-
工厂 bean
- 普通bean,在配置文件中定义 bean 类型就是返回类型
- 工厂bean,在配置文件中定义 bean 类型可以和返回类型不一样。
- 创建类,让这个类作为bean,实现接口 FactoryBean
- 实现接口内的方法,在实现的方法中定义返回的 bean 类型。getObject()
-
bean 的作用域
-
在 spring 中,可以设置创建的 bean 是单实例或者多实例
-
在默认情况下是单实例。
-
通过设置 bean 的 scope 属性值来进行调整
- singleton:默认,单实例。饿汉式,在加载xml文件时候创建实例对象
- prototype: 多实例。懒加载。在通过方法获取 bean 时才会创建对象。
-
-
bean 的生命周期
对象从创建到销毁的过程
-
执行无参构造
-
调用set方法,为bean的属性设置值和对其他 bean 引用
-
将 bean 的实例传递给 bean 的后置处理器,执行
postProcessBeforeInitialization()
方法 -
调用bean的初始化的方法。(需要配置)
bean 的 init-method 属性,值为方法名
-
把 bean 的实例传递给 bean 的后置处理器方法,执行
postProcessAfterInitialization()
方法 -
bean对象获取
-
当容器关闭时,调用bean的销毁方法(需要配置)
bean 的 destory-method 属性,值为方法名
,需要手动销毁// 手动销毁bean ClassPathXmlApplicationContext context= new ClassPathXmlApplicationContext(); context.close();
在不添加后置处理器相关时,取消步骤 3、5。
添加后置处理器
创建类,实现接口 BeanPostProcessor ,创建后置处理器
implements BeanPostProcessor
在 xml 文件中进行配置
<bean id="" class=""></bean>
配置完成后,会给xml文件内的所有 bean 都添加后置处理器。
-
-
基于 xml 的自动装配
自动装配,即指定装配规则(属性名或属性类型),spring 自动将匹配的属性值进行注入。
在 xml 文件配置 bean 时,使用
autowire
属性。 autowire 属性常用的2个值
- byName:通过属性名注入,注入值的 bean 的 id 值和类属性名要一致。
- byType:根据属性类型注入
-
外部属性文件的注入
示例 druid 数据连接池配置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverclass}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean>
创建 properties 文件,编写配置信息
jdbc.driverclass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/user jdbc.username=root jdbc.password=root
引入xml 命名空间 context,引入外部属性文件
<context:property-placeholder location="classpath:jdbc.properties"/>
-
-
基于注解的方式实现
注解是代码特殊标记,格式为: @注解名(属性名=属性值,属性名=属性值)
注解可以作用在类上,方法上,属性上
使用注解是为了简化 xml 文件配置。
-
bean 管理中 创建对象注解
- @Component 普通
- @Service
- @Controller
- @Repository 可以用在 dao 层
需要引入 spring-aop
在 xml 中开启组件扫描
在类中使用注解
<cotext:component-scan base-package="com.edu.test.dao"></cotext:component-scan>
// value 值为 xml 中的 id ,可以省略不写 // 如果不写,则默认为 类名(首字母小写) @Component(value="user") public class UserServcie{ public void add(){} }
-
基于注解实现输入注入
- @Autowired:根据属性类型进行自动装配
- @Qualifier:根据属性名称进行注入
- @Resource:可以根据类型注入,可以根据名称注入
- @Value:注入普通类型属性
@Qualifier 和 @Autowired 配合使用。在一个接口具有多个实现类时,通过 @Autowired 配置自动注入命名,然后使用 @Qualifier 对类进行注入
-
四、关于纯注解开发
配置类,用于替代 xml 配置文件
@COnfiguration // 作为配置类,替代xml配置文件
@ComponentScan(basePackage={"com.edu.mapper"}) //扫描
public class SpringConfig{
}
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);