spring框架简介
1.简介
1.Spring是轻量级的开源 的JavaEE框架
2.Spring可以解决企业应用开发的复杂性
3.Spring有两个核心部分:IOC和AOP
(1)IOC:控制反转,把创建对象过程交给 Spring 进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
4、Spring 特点
(1)方便解耦,简化开发
(2)Aop 编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低 API 开发难度
总结:Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器(框架)
2.组成
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
- 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
- Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 * Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
- Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
什么是耦合?
耦合是指两个实体相互依赖于对方的一个量度。
分为以下几种:
- 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。
- 数据耦合:一个模块访问另一个模块时,彼此之间是通过简单数据参数 (不是控制参数、公共数据结构或外部变量) 来交换输入、输出信息的。
- 标记耦合 :一组模块通过参数表传递记录信息,就是标记耦合。这个记录是某一数据结构的子结构,而不是简单变量。
- 控制耦合:如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。
- 外部耦合:一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
- 公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
- 内容耦合:如果发生下列情形,两个模块之间就发生了内容耦合
(1) 一个模块直接访问另一个模块的内部数据;
(2) 一个模块不通过正常入口转到另一模块内部;
(3) 两个模块有一部分程序代码重迭(只可能出现在汇编语言中);
(4) 一个模块有多个入口。
IOC(概念和原理)
1、什么是 IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
(2)使用 IOC 目的:为了耦合度降低
(3)做入门案例就是 IOC 实现
2、IOC 底层原理
(1)xml 解析、工厂模式、反射
3、画图讲解 IOC 底层原理
IOC (BeanFactory 接口)
1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
2、Spring 提供 IOC 容器实现两种方式:(两个接口)
(1)BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
- 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
员进行使用 - 加载配置文件时候就会把在配置文件对象进行创建
3、ApplicationContext 接口有实现类
什么是DI?和IOC有什么区别?
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)
本质上IoC和DI是同一思想下不同维度的表现 ,用通俗的话说就是,IoC是bean的注册,DI是bean的初始化
简单的IoC控制反转代码实现,定义测试的Bean,Student和Teacher
public class Teacher {
private String tName;
// ....get set方法省略
}
public class Student {
private String name;
private String age;
private Teacher teacher;
// ....get set方法省略
}
BeanDefined类,对bean的描述类:
public class BeanDefined {
// bean的id
private String beanId;
// bean的文件路径
private String classPath;
public String getBeanId() {
return beanId;
}
public void setBeanId(String beanId) {
this.beanId = beanId;
}
public String getClassPath() {
return classPath;
}
public void setClassPath(String classPath) {
this.classPath = classPath;
}
}
BeanFactory — 生成Bean的容器类:
public class BeanFactory {
// 存放bean的集合
private List<BeanDefined> beanDefinedList;
public List<BeanDefined> getBeanDefinedList() {
return beanDefinedList;
}
public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
this.beanDefinedList = beanDefinedList;
}
/**
* 获取bean实例
*
* @param beanId
* @return
* @throws Exception
*/
public Object getBean(String beanId) throws Exception {
Object instance;
for (BeanDefined bean : beanDefinedList) {
if (beanId.equals(bean.getBeanId())) {
String classPath = bean.getClassPath();
Class classFile = Class.forName(classPath);
// 在spring中调用默认的构造方法,这里我们也调用默认的构造方法
instance = classFile.newInstance();
return instance;
}
}
return null;
}
}
测试类:
public class Test {
public static void main(String[] args) throws Exception {
// 1、声明注册bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("student");
beanObj.setClassPath("com.pojo.Student");
List<BeanDefined> beanList = new ArrayList<BeanDefined>();
beanList.add(beanObj);
// 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
BeanFactory factory = new BeanFactory();
factory.setBeanDefinedList(beanList);
// 3、开发人员向BeanFactory索要实例对象
Student student = (Student) factory.getBean("student");
System.out.println(student);
}
}
测试结果截图:
从代码里面可以看出来,我们是没有直接new学生类的,主要的思想是,定义BeanDefined对象添加进集合中,通过BeanFactory为我们生产出需要的对象,其中用到的核心技术就是:反射
用代码实现简单的依赖注入:
BeanDefined类需要做一定的修改:
public class BeanDefined {
// bean的id
private String beanId;
// bean的文件路径
private String classPath;
// 存放属性的集合
private Map<String, String> propertyMap = new HashMap<>();
// ....省略set和get方法
}
BeanFactory类需要做如下的修改:
public class BeanFactory {
// 存放bean的集合
private List<BeanDefined> beanDefinedList;
public List<BeanDefined> getBeanDefinedList() {
return beanDefinedList;
}
public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
this.beanDefinedList = beanDefinedList;
}
/**
* 获取bean实例
*
* @param beanId
* @return
* @throws Exception
*/
public Object getBean(String beanId) throws Exception {
Object instance;
for (BeanDefined bean : beanDefinedList) {
if (beanId.equals(bean.getBeanId())) {
String classPath = bean.getClassPath();
Class classFile = Class.forName(classPath);
// 在spring中调用默认的构造方法,这里我们也调用默认的构造方法
instance = classFile.newInstance();
// 获取bean的属性配置
Map<String, String> propertyMap = bean.getPropertyMap();
if(propertyMap !=null) {
setValue(instance, classFile, propertyMap);
}
return instance;
}
}
return null;
}
/**
* 依赖注入的方法
*
* @param instance 当前的实例对象
* @param classFile 当前实例对象所关联的类文件
* @param propertyMap 属性
*/
public void setValue(Object instance, Class classFile, Map<String, String> propertyMap) throws Exception {
if(propertyMap !=null ) {
/***
* 获取map的所有属性配置
*/
Set<String> proper = propertyMap.keySet();
for(String string : proper) {
// 通过字符串拼接,拼出set方法名
char c = string.toUpperCase().charAt(0);
String s = "set" + c + string.substring(1);
// 获取当前属性的类型
Field field = classFile.getDeclaredField(string);
// 根据属性的类型进行调用
Method m = instance.getClass().getMethod(s, field.getType());
/**
* 直接try注入普通类型,或者catch注入bean工厂中的其他类型
*/
try {
m.invoke(instance, propertyMap.get(string));
} catch (Exception e) {
m.invoke(instance, getBean(propertyMap.get(string)));
}
}
}
}
}
测试类代码需要做如下修改:
public class Test {
public static void main(String[] args) throws Exception {
// 1、声明注册bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("student");
beanObj.setClassPath("com.pojo.Student");
// 设置 property
Map<String, String> propertyMap = beanObj.getPropertyMap();
propertyMap.put("name", "kxm");
propertyMap.put("age", "22岁");
propertyMap.put("teacher", "teacher");
// 注册教师类
BeanDefined teacher = new BeanDefined();
teacher.setBeanId("teacher");
teacher.setClassPath("com.pojo.Teacher");
List<BeanDefined> beanList = new ArrayList<BeanDefined>();
beanList.add(beanObj);
beanList.add(teacher);
// 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
BeanFactory factory = new BeanFactory();
factory.setBeanDefinedList(beanList);
// 3、开发人员向BeanFactory索要实例对象
Student student = (Student) factory.getBean("student");
System.out.println(student);
}
}
测试结果截图:
仔细分析代码,我们可以发现,没有显示的new对象,也没用用set方法去赋值,但是模拟出来了依赖注入的效果,这也是Spring中依赖注入的原理,当然这里是最简单的实现
我对IoC(控制反转)和DI(依赖注入)的理解
在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
这是我对Spring的IoC(控制反转)的理解。DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。
依赖注入
构造器注入
通过无参构造方法来创建
1、User.java
public class User {
private String name;
public User() {
System.out.println("user无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
2、beans.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="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
</bean>
</beans>
3、测试类
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//在执行getBean的时候, user已经创建好了 , 通过无参构造
User user = (User) context.getBean("user");
//调用对象的方法 .
user.show();
}
结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!
通过有参构造方法来创建
1、UserT . java
public class UserT {
private String name;
public UserT(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
2、beans.xml 有三种方式编写
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="kuangshen2"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="kuangshen2"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
3、测试
@Test
public void testT(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserT user = (UserT) context.getBean("userT");
user.show();
}
结论:在配置文件加载的时候。其中管理的对象都已经初始化了!
Set注入
要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .
测试pojo类 :
Address.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Student.java
package com.kuang.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setBooks(String[] books) {
this.books = books;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public void setGames(Set<String> games) {
this.games = games;
}
public void setWife(String wife) {
this.wife = wife;
}
public void setInfo(Properties info) {
this.info = info;
}
public void show(){
System.out.println("name="+ name
+ ",address="+ address.getAddress()
+ ",books="
);
for (String book:books){
System.out.print("<<"+book+">>\t");
}
System.out.println("\n爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
System.out.println("wife:"+wife);
System.out.println("info:"+info);
}
}
扩展的注入
1、常量注入
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
</bean>
测试:
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
2、Bean注入
注意点:这里的值是一个引用,ref
<bean id="addr" class="com.kuang.pojo.Address">
<property name="address" value="重庆"/>
</bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
</bean>
3、数组注入
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</array>
</property>
</bean>
4、List注入
<property name="hobbys">
<list>
<value>听歌</value>
<value>看电影</value>
<value>爬山</value>
</list>
</property>
5、Map注入
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
</map>
</property>
6、set注入
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>
7、Null注入
<property name="wife"><null/></property>
8、Properties注入
<property name="info">
<props>
<prop key="学号">20190604</prop>
<prop key="性别">男</prop>
<prop key="姓名">小明</prop>
</props>
</property>
测试结果:
9、p命名和c命名注入
User.java :【注意:这里没有有参构造器!】
public class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1、P命名空间注入 : 需要在头文件中加入约束文件
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!--P(属性: properties)命名空间 , 直接注入属性-->
<bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>
2、c 命名空间注入 : 需要在头文件中加入约束文件
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--C(构造: Constructor)命名空间 , 使用构造器注入-->
<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>
发现问题:爆红了,刚才我们没有写有参构造!
解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入!
测试代码:
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
Spring中bean的两种方式
1 、Spring 有两种类型 bean ,一种普通 bean ,另外一种工厂 bean (FactoryBean )
2 、普通 bean :在配置文件中定义 bean 类型就是返回类型
3 、工厂 bean :在配置文件定义 bean 类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
public class MyBean implements FactoryBean<Course> {
//定义返回 bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname( "abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
< bean id= "myBean" class= "com.atguigu.spring5.factorybean.MyBean">
</ bean>
@Test
public void test3() {
ApplicationContext context =
new ClassPathXmlApplicationContext( "bean3.xml");
Course course = context.getBean( "myBean", Course. class);
System. out .println(course);
}
Spring管理bean的作用域
1 、在 Spring 里面,设置创建 bean 实例是单实例还是多实例
2 、在 Spring 里面 里面,默认情况下, ,默认情况下,bean 是单实例对象
public void TestCollection2 {
ApplicationContext context =
new ClassPathXmlApplicationContext(configLoction:"bean2.xml");
Book book1 = context.getBean(s:"book",Book.class);
Book book2 = context.getBean(s:"book",Book.class);
//book.test();
system.out.println(book1);
system.out.println(book1);
}
运行结果:
3 、如何设置单实例还是多实例
(1)在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
(2)scope 属性值
第一个值 默认值,singleton,表示是单实例对象
第二个值 prototype,表示是多实例对象
(3)singleton 和 prototype 区别
第一 singleton 单实例,prototype 多实例
第二 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用
getBean 方法时候创建多实例对象
Spring管理bean的生命周期
1 、生命周期
(1)从对象创建到对象销毁的过程
2 、bean 生命周期
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(4)bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
3 、演示 bean 生命周期
public class Orders {
//无参数构造
public Orders() {
System. out .println(" " 第一步 执行无参数构造创建 n bean 实例" ");
}
private String oname;
public void setOname(String oname) {
this. oname = oname;
System. out .println(" " 第二步 调用 t set 方法设置属性值" ");
}
//创建执行的初始化的方法
public void initMethod() {
System. out .println(" " 第三步 执行初始化的方法" ");
}
//创建执行的销毁的方法
public void destroyMethod() {
System. out .println(" " 第五步 执行销毁的方法" ");
}
}
< bean id= "orders" class= "com.atguigu.spring5.bean.Orders" init- -
method= "initMethod" destroy- - method= "destroyMethod">
< property name= "oname" value=" " 手机" "></ property>
</ bean>
@Test
public void testBean3() {
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext( "bean4.xml");
Orders orders = context.getBean( "orders", Orders. class);
System. out .println(" " 第四步 获取创建 n bean 实例对象" ");
System. out .println(orders);
//手动让 bean 实例销毁
context.close();
}
第一步:执行无参数构造创建bean实例
第二步:调用set方法设置属性值
第三步:执行初始化的方法
第四步:获取创建bean实力对象
第五步:执行销毁的方法
4 、bean 的后置处理器,bean 生命周期有七步
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3 3 )把 n bean 实例传递 n bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
( (5 )把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
5 、演示添加后置处理器效果
(1)创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost 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= "myBeanPost" class= "com.atguigu.spring5.bean.MyBeanPost"></ bean>
第一步:执行无参数构造创建bean实例
第二步:调用set方法设置属性值
在初始化之前执行的方法
第三步:执行初始化的方法
在初始化之后执行的方法
第四步:获取创建bean实例对象
com.atguigu.spring5.bean.Orders@43bd930a
第五步:执行销毁的方法