Spring原理篇(1)--Spring创建Bean的生命周期

@TOC# Spring系列
记录在程序走的每一步___auth:huf


拨开云雾见天日 守得云开见月明


一、Spring创建Bean的生命周期

在Spring的入口开始

package com.example;
import com.example.service.StudentService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
        StudentService studentService = (StudentService) run.getBean("studentService");
        System.out.println(studentService);
    }
}

直接使用SpringBoot, 在ConfigurableApplicationContext 进行加载 StudentService 以下是StudentService的实体类 StudentService 获取直接从Spring容器中获取. 跟直接new 出来的类有天壤之别; 其中一大块就是属性注入问题; 属性注入就要提起 关于BeanDefinition 与 Bean之间的关系 在后面的文章中会详细介绍; 本期文章中不会有体现;

package com.example.service;
import com.example.entity.Student;
public interface StudentService {
...
}
package com.example.service.impl;
import com.example.service.StudentService;
@Service(value="studentService")
public class StudentServiceImpl implements StudentService {
..
}

以下是一个Bean的生命周期图<简化版>

Spring容器启动
通过反射加载对象
UserService,Class
构造方法
默认无参构造方法
当有多个构造方法时,并且没有无参构造方法时,应当使用Autowired来指定
普通对象
依赖注入
初始化前PostConstruct
初始化InitializingBean
初始化后aop
代理对象
bean

1: 利用该类的构造方法来实例化一个对象(如果说有多个构造方法,那么Spring会自行选择,选择规则是 在没有@Autowired的时候 就会选择默认的,在没有默认的, 就会选择唯一一个 如果有多个就会报错,此时需要在构造方法内指定@Autowired);

2: 得到一个对象后 查看其属性是否被 @Autowired注解 ; 如果有那么Spring会从容器中寻找该对象进行注入;

3: 依赖注入之后,Spring会自行判断该对象是否实现了BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口 如果有.那么就会调取其实现方法setBeanName()、setBeanClassLoader()、 setBeanFactory();那Spring就会调用这些方法并传入相应的参数(Aware回调)

4:Aware回调后,那么就会判断该类是否存在PostConstruct注解 了,如果存在,Spring会调用当前对象的此方法(初始化前)

5:紧接着,Spring会判断该对象是否实现了InitializingBean接口,如果实现了,就 表示当前对象必须实现该接口中的afterPropertiesSet()方法,那Spring就会调用当前对象中的afterPropertiesSet()方法(初始化);

6:最后判断:Spring是否需要Aop,如果不需要.那么类就创建完毕(此时是普通对象);如果需要;那么就会 动态代理 由代理类来实现AOP;此时就是代理对象; 这个需要注意 普通对象与代理对象的区别! 代理对象 实际是就是为了实现AOP; 最后附上代码图 Debug进行解释在这里插入图片描述

Spring中使用Cglib 进行动态代理的呢;此处以伪代码进行解释

package com.example.service.impl;
import com.example.entity.Student;
import com.example.service.StudentService;
/**
 * 此处为cglib自己生产的代理类 并且继承
 * auth:huf
 */
public class StudentServiceProxy extends StudentServiceImpl{
    StudentService target;// 使用的是是前面创建的Java普通对象;注意是普通对象
    public int insert(Student stu){
        /**
         * AOP的前置动作;Before
         */
        //这个地方insert并非使用super.insert方法;
        target.insert(stu);
        /**
         * AOP的后置动作;
         */
    }
}

AOP大致流程

AOP就是进行动态代理,在创建一个Bean的过程中,Spring在最后一步会去判断当前正在 创建的这个Bean是不是需要进行AOP,如果需要则会进行动态代理。如何判断当前Bean对象需不需要进行AOP:
1. 找出所有的切面Bean
2. 遍历切面中的每个方法,看是否写了@Before、@After等注解
3. 如果写了,则判断所对应的Pointcut是否和当前Bean对象的类是否匹配
4. 如果匹配则表示当前Bean对象有匹配的的Pointcut,表示需要进行AOP 利用cglib进行AOP的大致流程:
1). 生成代理类StudentServiceProxy,代理类继承StudentServiceImpl
2). 代理类中重写了父类的方法,比如StudentServiceImpl中的insert()方法
3). 代理类中还会有一个target属性,该属性的值为被代理对象(也就是通过 UserService类推断构造方法实例化出来的对象,进行了依赖注入、初始化等步骤的 对象)
4). 代理类中的test()方法被执行时的逻辑如下: a. 执行切面逻辑(@Before) b. 调用target.insert() 当我们从Spring容器得到StudentServiceImpl的Bean对象时,拿到的就是UserServiceProxy所生 成的对象,也就是代理对象。 StudentServiceImpl代理对象.insert()—>执行切面逻辑—>target.insert(),注意target对象不是代理 对象,而是被代理对象。

在复习过程中 修正之前跟一名同事 哲哲 说的 一个Spring原理:
注:Spring会根据入参的类型和入参的名字去Spring中找Bean对象,(以单例Bean为例, Spring会从单例池那个Map中去找):
1. 先根据入参类型找,如果只找到一个,那就直接用来作为入参
2. 如果根据类型找到多个,则再根据入参名字来确定唯一一个
3. 最终如果没有找到,则会报错,无法创建当前Bean对象
//在什么时候会有多个Bean同时存在在一个容器中: 代码举例

package com.example.config;
import com.example.entity.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * BeanTest
 */
@Configuration
public class BeanTestConfig {
    /**
     * 这种情况下 容器就会存在多个Bean并且 相互是独立的  
     * 先通过类型进行查找. 这时候会找到三个Bean 
     * 然后再通过名字 student1 最终定位到一个Bean; 
     * @return
     */
    @Bean
    public Student student1(){
        return  new Student();
    }
    @Bean
    public Student student2(){
        return  new Student();
    }
}

总结

Spring中的 Bean的生命周期大致如上. Spring @Transactional 也是通过AOP实现的;其原理 就是把autocommit 由true改为false; 由代理类进行Commit; Spring原理 会持续更新 更新时间为每个星期 三篇左右;

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 春天是一个美好的季节,bean的创建bean的生命周期与此同样美好。Bean的创建是指在Spring容器中创建bean对象的过程,而bean的生命周期指定义bean实例的生命周期,从创建到销毁的过程。 ### 回答2: Spring创建bean的过程如下: 1. 配置bean:通过XML配置文件或Java注解将要创建bean进行配置,包括bean的类、属性、依赖关系等。 2. 加载bean定义:Spring容器根据配置文件或注解信息,将bean的定义加载到内存中。 3. 创建实例:Spring容器根据bean的定义,使用Java反射机制实例化bean对象。 4. 设置属性:Spring容器通过依赖注入的方式,将bean所依赖的属性注入到bean实例中。 5. 调用初始化方法:如果bean实现了InitializingBean接口或在配置文件中通过init-method属性指定了初始化方法,Spring容器在创建bean对象后会调用其初始化方法。 6. bean可用:经过以上步骤,Spring容器创建完成了bean,并将其放入容器中,可以使用该bean了。 7. 调用销毁方法:如果bean实现了DisposableBean接口或在配置文件中通过destroy-method属性指定了销毁方法,当容器关闭时,会调用bean的销毁方法。 Bean的生命周期包括以下阶段: 1. 实例化:Spring容器根据bean的定义和配置,使用反射机制实例化bean对象。 2. 设置属性:将bean的依赖属性注入到bean实例中。 3. 初始化:Spring容器调用bean的初始化方法,执行一些初始化逻辑。 4. 使用:bean实例可以被应用程序使用。 5. 销毁:当容器关闭时,调用bean的销毁方法,执行一些清理逻辑。 在整个生命周期中,开发人员可以通过配置文件或注解方式指定各个阶段的行为,如指定初始化方法、销毁方法、依赖注入等。Spring容器负责管理bean的生命周期,从而提供了更好的灵活性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Like Java Long Time

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值