Spring 概述
- Spring 是一个 轻量级的 J2EE 开源框架
- 可以解决企业应用开发的复杂性
- Spring 的核心部分:IOC 和 AOP
- 特点
- 方便解耦,简化开发
- AOP 编程
- 方便程序测试
- 方便与其他框架整合
- 方便事务操作
- 降低API开发难度
IOC(控制反转)
把对象的创建和对象间的调用交给 Spring容器管理
目的: 降低 耦合度
底层原理:
- xml解析
- 工厂模式
- 反射
IOC思想
IOC 思想基于 IOC容器完成, IOC 容器底层 就是 对象工厂
Spring 提供IOC容器的两个接口(方法)
BeanFactory
: IOC 容器基本实现,是Spring内部的使用接口,不提供给开发者使用加载配置文件的时候不会创建对象,只有使用的时候才会创建对象(懒汉式)
ApplicationContext
: BeanFactory 的子接口,提供更强大的功能加载配置文件就会创建对象
ICO操作 Bean管理
- 基于 xml 文件
- 基于注解
DI(依赖注入)
DI 是 IOC中的一种具体实现,DI 需要在创建对象的基础之上完成
Bean的生命周期
五步
- 通过构造器创建Bean实例(无参构造)
- 属性注入(为Bean的属性设置值,或者对 其他Bean 引用)
- 调用 Bean 的初始化方法(需要进行配置)
- 使用
- 销毁(需要配置销毁的方法)
七步(多出的两部分别在 初始化前后执行)
这个是使用 bean 的后置处理器 BeanPostProcessor
(要在配置文件中配置才能生效)
创建一个类 实现 BeanPostProcessor
,重写方法
前置增强postProcessBeforeInitialization
后置增强 postProcessAfterInitialization
- 通过构造器创建Bean实例(无参构造)
- 属性注入(为Bean的属性设置值,或者对 其他Bean 引用)
postProcessBeforeInitialization
前置增强- 调用 Bean 的初始化方法(需要进行配置)
postProcessAfterInitialization
后置增强- 获取
- 销毁
把代码第四步❌剔除
MyBeanPostProcessor.java
后置处理器
package com.bikakaso.processor;
import com.bikakaso.pojo.Orders;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import javax.annotation.PostConstruct;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("3. 我是前置增强");
if (bean instanceof Orders) {
Orders orders = (Orders) bean;
orders.setName("截胡了");
return orders;
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("6. 后置增强");
if (bean instanceof Orders) {
Orders orders = (Orders) bean;
orders.setName("不好意思,不让你截");
return orders;
}
return bean;
}
}
Orders.java
实体类
package com.bikakaso.pojo;
import org.springframework.beans.factory.InitializingBean;
public class Orders implements InitializingBean {
private String name;
private double price ;
int i = 1;
public void setPrice(double price) {
this.price = price;
if ( i == 1) {
System.out.println("调用 setPrice 方法");
}
i++;
}
public Orders() {
System.out.println(" 1. 调用 无参构造");
}
public void setName(String name) {
this.name = name;
if ( i == 1) {
System.out.println("2.调用 setName 方法");
}
i++;
}
public void initMethod() {
System.out.println("5. 初始化方法,这个步骤需要自己配置");
}
public void destroyMethod() {
System.out.println("8. 销毁bean");
}
@Override
public String toString() {
return "Orders{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
// 这一步 实体类需要实现 InitializingBean 接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4. 前置处理后,初始化前");
}
}
bean2.xml
<?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="orders" class="com.bikakaso.pojo.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="订单1"/>
</bean>
<bean id="myBeanPostProcessor" class="com.bikakaso.processor.MyBeanPostProcessor"/>
</beans>
测试
@Test
public void test2() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean2.xml");
Orders orders = applicationContext.getBean("orders", Orders.class);
// Orders orders2 = applicationContext.getBean("orders", Orders.class);
System.out.println("7. 获取到 bean");
System.out.println(orders.toString());
applicationContext.close();
}
xml自动装配(自动注入)
byName
根据定义的属性名 注入,配置文件中的 bean 的 id 需要和 属性名相同
但是
byName 找不到 相同的 id 时,还会再根据 类型注入
Empl.java
public class Empl {
// 自动装配 byName, 配置文件中 通过 dept 这个名字 注入属性
private Dept dept;
private Dept dept1; // 测试 根据类型注入,3行需注释,重写 set 方法
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Empl{" +
"dept=" + dept +
'}';
}
}
Dept.java
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
bean.xml
<?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="empl" class="com.bikakaso.autowire.Empl" autowire="byName"/>
<bean id="dept" class="com.bikakaso.autowire.Dept"/>
<bean id="dept1" class="com.bikakaso.autowire.Dept"/> // 测试根据类型注入,10行需注释
</beans>
测试
// 自动装配
@Test
public void test3() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean3.xml");
Empl empl = applicationContext.getBean("empl", Empl.class);
System.out.println(empl.toString());
}
结果
正常情况
找不到 name
byType
byType 是根据 bean 的 class 属性来注入的,同一个类的 bean 只能存在一个,否则会报错