zoukankan      html  css  js  c++  java
  • spring生命周期随笔

    spring生命周期上:

    要注意的是spring启动的时候已经经过了spring的生命周期了

    transformBeanName(name)

    getSingleton(beanName)是可以拿到

    getObjectForBeanInstance 是不是factoryBean
    name 程序员传入、beanName 真名

    双重机制校验
    普通bean直接返回
    是factoryBean执行下面的逻辑

    从缓存中调用
    factoryObejctCanche
    当前缓存没有 强制转换成factoryBean ,因为他要调用getObject方法
    doGetObjectFromFactoryBean

    // 调用BeanPostProcessor执行初始化后的逻辑,主要就是进行AOP

    调用初始化之后的方法 因为他可能要进行aop做动态代理
    得到的对象要看他是不是实现了factoryBean

    所以FactoryBean相当于是懒加载 。只有在调用getBean(factoryBeanName)的时候才会调用getObject方法去获取User 对象

    getObject的user对象会放到容器中:
    就是factoryBeanObjectCache 容器中 而LubanFactoryBean就会放到singletonObjects 0:41:00

    beanFactroy是大工厂 ,spring中所有的Bean 都是由BeanFactory创建出来的 。它可以创建普通bean 和特殊bean 、单例bean原型bean
    FactoryBean是通过beanFactory 创建出来的
    FactoryBean是一个小的工厂 ,只能产生一个对象。 或者scope是 原型的 ,可以产生同一个类型的多个对象

    factoryBean的作用 有的时候我们希望自己构造一个对象,把他放到Ioc容器中

    这边getBean("user") 拿不到User这个对象 ,因为这个User对象不是一个配置类, 不能够生成Bean定义

    @component
    public class UserService{
    @Autowired
    private UserMapper userMapper;

    }
    UserMapper接口 ,需要把UserMapper接口的代理对象注册到Ioc容器中。。 既可以有代理对象 又需要注册到容器中
    在我们的容器中我们需要一个UserMapper的代理对象

    还有啥方式: 如何把我们自己new 出来的对象 放到容器中呢??
    1、@Bean 功能比较单一 ,只能写在方法上 , 这个方法内部也能够 弄一个代理对象出来
    2、class 实现 FactoryBean 接口之外,还能够 实现其他接口 BeanClassLoaderAware
    回调函数可以 拿到这个类是哪个 类加载器加载
    00:00 - 00:58:543 都在讲一个东西就是FactoryBean

    bean的生命周期
    进行扫描,扫描类
    生成Bean

    推断构造方法 , 加载类之后要实例化对象的话,多 个构造方法要选哪一个呢 所以会去推断构造方法
    属性赋值就是依赖注入

    有一个问题,当我们在扫描的时候,扫描到userService这个类的时候,我们没有去加载这个类,我们说的加载这个类指的是生成这个类的class
    对象放到jvm中去,我们在扫描的时候没有做到这一步。。。 那我们如何发现UserService这个类上面是否有component这个注解呢 ,第一步进行扫描,然后我们用的asm技术
    解析字节码文件 识别这个类的信息 生成一个beanDefintion

    入口 :

    怎样实例化非懒加载的单例ban

    合并之后的bd 叫做rootBd
    合并之前的叫做 genericBd
    bd常用的类型
    bd是接口 有实现类
    genericbd 是支持拥有父
    rootbd 不支持parent
    创建bean 一定是拿合并之后的bd 就是拿rootbd,
    不会去改扫描出来的bd 就是genricBd
    就只是会生成mergedBd

    beanName --》mergedMap ==》genercicBeanDefintion -parent -》rootBeanDefintion

    合并bean定义

    抽象的不能生成bean定义 抽象类不能实例化--》

    @dependSon 注解
    程序员自定义的

    a depends on b
    b depends on a
    无法创建

    @component
    @dependson("orderService")
    public class UserService(){
    }

    @component
    @dependson("userService)
    public class OrderService(){
    }

    RequestScope AbstractRequestAttributesScope
    SessionScope AbstractRequestAttributesScope

    "RequestScope":RequestScope
    "session":SessionScope
    get方法
    结论:

    "request" ,UserService -->>Bean对象 request.getAttribute().get("beanName")
    "session" ,UserService -->>Bean对象 session.getAttribute().get("beanName")

    doCreateBean spring自带的创建方法
    resolveBeforeInstantiation(beanName, mbdToUse); 让程序员自己返回一个bean 实现方法用bean的后置处理器

    bean的后置处理器 ,spring在创建bean的过程中,我们可以设置一些bean的后置处理器去干涉soring创建bean的过程

    实例化之前的bean后置处理器 得到bean 则再执行初始化后的bean后置处理器 因为它跟aop 有关系 不能够拒绝aop

    填充属性 @Autowired
    populateBean(beanName, mbd, instanceWrapper); //

    初始化 和 BeanPostProcessor 正常AOP BeanPostProcessor
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    initializeBean 中 1、 执行aware
    2、 初始化之前 @pointConstruct
    3、初始化 调用 实现了InitializingBean 接口的
    4、 初始化后

    对于任何一个bean 他都有一个beanName

    还要判断从单例池拿到的bean是不是一个factoryBean

    如果是原型的就直接去创建bean 不去单例池拿了

    createBean 是如何创建Bean

    第一步:
    加载类
    beanName mbd
    如何返回class对象

    AbstractBeanDefinition 的
    @Nullable
    private volatile Object beanClass; // String Class
    获取BeanDefinition中所指定的beanClass属性的值,beanClass属性的类型为Object,可以指定为某个类名
    // className可以有SpEL,所以需要解析

    @Component
    public class UserService(){
    @value("#{orderService}") // 可以注入成功
    private OrderService orderService;

    public void test (){

    sout(orderService;)}
    }

    @value("#{orderService1}") 报错

    表示是表达式

    @value("${orderService1}") 报错
    $表示是占位符 需要填充 用什么填充呢 ,用的是spring的Enviroment

    1、定义properties
    2、vm options 的时候指定 -D LunbanXX=123

    @Autowired 是先byType 再byName

    rootbeandefintion 中 beanclass = "com.lunban.UserService"
    beanClass 是一个全限定名去加载类,然后重新设置回bean的class属性
    asm技术

    spring用什么类加载器 去加载类呢 ?

    AbstractBeanFactory  
     	@Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
    

    Thread.CurrentThread().setContextClassLoader(XXX);
    applicationContext.getBeanFactroy().setBeanClassLoder(xxx) 程序员自己指定的类加载器
    会利用BeanFactory所设置的类加载器来加载类,。

    AbstractBeanFactory 类 
     	@Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
    

    如果没有上面的BeanFactory没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载

    ClassUtils.getDefaultClassLoader()

    1. 优先获取当前线程中的ClassLoader(正常情况下,就是AppClassLoader)
    2. 如果为空,则获取加载ClassUtils类的类加载器(正常情况下,就是AppClassLoader,但是如果是在Tomcat中运行,那么则会是Tomcat中为每个应用所创建的WebappClassLoader,tomcat会在前面设置)
    3. 如果为空,那么则是bootstrap类加载器加载的ClassUtils类,那则获取系统类加载器进行加载 系统类加载器默认返回的是appClassLoader

    luban 第三期spring生命周期下 00:53:19
    什么叫做bootstrap加载 ,spring项目的jar包放到 jre/lib下 放到这个目录下面的类 都会用bootstrap 加载

    类加载器的 看jvm 里面有讲。。。。。。。。。

    // 如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载
    如果BeanFactory所设置的类加载器来加载类为空,则获取加载ClassUtils类的类加载器(正常情况下,就是AppClassLoader,但是如果是在Tomcat中运行,那么则会是Tomcat中为每个应用所创建的WebappClassLoader)

    asm技术解析字节码生成bd文件

    Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 对象 在doCreateBean之前

    Object beanInstance = doCreateBean(beanName, mbdToUse, args);

    // 4.1、执行Aware
    invokeAwareMethods(beanName, bean); BeanNameAware BeanClassLoaderAware BeanFactoryAware

    UserService 实现了InitializingBean,ApplicatioContextAware(对ApplicationContextAwareProcessor)

    // 4.2、初始化前
    ApplicatioContextAware 在 初始化前执行 对ApplicationContextAwareProcessor ---》applyBeanPostProcessorsBeforeInitialization

    // 4.2、初始化前
    @pointConstruct注解 ---》applyBeanPostProcessorsBeforeInitialization InitDestroyAnnotationBeanPostProcess --》 找注解 pointConstruct注解 preDestroy 注解
    InitDestroyAnnotationBeanPostProcess -》CommonAnnotationBeanPostProcess 的父类

    // 4.3、初始化
    afterPropertiesSet 在初始化时候执行 ---》invokeInitMethods(beanName, wrappedBean, mbd);

    有一个判断逻辑 为什么 不行 ,因为luBanBeanPostProcess 的postProcessBeforeInitialization 方法返回空了,而且因为luBanBeanPostProcess 优于InitDestroyAnnotationBeanPostProcess 执行,只要保证
    luBanBeanPostProcess 的postProcessBeforeInitialization 方法执行不为空 就能让 CommonAnnotationBeanPostProcess(InitDestroyAnnotationBeanPostProcess) 执行 的postProcessBeforeInitialization (调用@pointConStruct方法)
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {

    	Object result = existingBean;
    	for (BeanPostProcessor processor : getBeanPostProcessors()) {
    		// BPP1--》BPP2-->BPP3
    		Object current = processor.postProcessBeforeInitialization(result, beanName);
    		if (current == null) {
    			return result;
    		}
    		result = current;
    	}
    	return result;
    }
    

    上一个beanPostProcess 执行完之后没有返回 下一个bpp 就不会执行

    加载类
    实例化前 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessBeforeInstantiation
    实例化
    BeanDefinition的后置处理 --》 对bd进行操作 BeanDefinition的后置处理 MergedBeanDefinitionPostProcessor --》 postProcessMergedBeanDefinition
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
    try {
    // 运行修改合并好了的BeanDefinition
    // 这里会查找@Autowired的注入点(InjectedElement),并把这些注入点添加到mbd的属性externallyManagedConfigMembers中
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    }
    catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    "Post-processing of merged bean definition failed", ex);
    }
    mbd.postProcessed = true;
    }
    }

    实例化后 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessAfterInstantiation
    填充属性
    填充属性后 --》 InstantiationAwareBeanPostProcessors 中的 postProcessPropertyValues 、postProcessProperties 进行依赖注入
    aware
    初始化前 --》 bpp postProcessBeforeInitialization
    初始化
    初始化后 --》 bpp postProcessAfterInitialization

    实例化前 --》 bpp InstantiationAwareBeanPostProcessor 只有他有 postProcessBeforeInstantiation 这边返回bean了就直接执行初始化后的方法
    初始化后 --》 bpp postProcessAfterInitialization
    // 实例化前
    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    if (bean != null) {
    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    }

    @Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    	Object bean = null;
    	// beforeInstantiationResolved为null或true
    	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    		// Make sure bean class is actually resolved at this point.
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			Class<?> targetType = determineTargetType(beanName, mbd);
    			if (targetType != null) {
    				// 实例化前
    				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    				if (bean != null) {
    					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    				}
    			}
    		}
    		mbd.beforeInstantiationResolved = (bean != null);
    	}
    	return bean;
    }
    



    ​ // 2、实例化
    ​ if (instanceWrapper == null) {
    ​ // 创建bean实例 new USerSerive()
    ​ instanceWrapper = createBeanInstance(beanName, mbd, args); 这里回进行推造构造方法 , 我们要选哪一个构造方法呢 后面会将
    ​ }

    实例化前返回对象就不会填充属性
    实例化后返回false 就不会填充属性

    @Component
    public class LubanMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanName.equals("userService")) {
            beanDefinition.setBeanClass(User.class); // 没用
    		 beanDefinition.setInitMethodName("initLuBan");
            beanDefinition.getPropertyValues().add("name","xxx");
        }
    }
    

    }

    @component
    public class UserService{
    public void initLuBan(){
    sout("initLuBan");
    }

    }

    在初始化的方法中
    invokeInitMethods(beanName, wrappedBean, mbd);

    西面这段代码在初始化的最后

    if (mbd != null && bean.getClass() != NullBean.class) {
    String initMethodName = mbd.getInitMethodName();
    if (StringUtils.hasLength(initMethodName) &&
    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    !mbd.isExternallyManagedInitMethod(initMethodName)) {
    invokeCustomInitMethod(beanName, bean, mbd); // init-method=""
    }
    }
    就会执行这段代码 很六六六 。。

    初始化的过程可以做验证 。。。。。 spring提供了各种钩子函数 。。。。

  • 相关阅读:
    HDFS高阶
    Flume学习笔记
    Yarn学习笔记
    二进制中1的个数
    二叉搜索树的后序遍历
    空指针
    web第十天总结
    绩效考核系统
    制作流程图,activity,好不容易找到的
    职业规划
  • 原文地址:https://www.cnblogs.com/tangliMeiMei/p/15265853.html
Copyright © 2011-2022 走看看