Spring源码复习

一、Spring源码

1.1 spring 依赖注入的方式有几种?

1.手动注入:通过XML进行配置bean属性
1.1Set方法
在这里插入图片描述
可以通过ByType,ByName进行赋值
1.2.构造方法注入
在这里插入图片描述
2.自动注入
2.1通过XML自动注入【set和构造方法】
2.2通过@Autowired自动注入
注入点:属性、构造方法、普通方法
遍历所有的注入点【方法—>注入点】
静态属性无法自动注入进去,源码会爆出非法异常

1.2 启动spring的两种方式

1.ClassPathXmlApplicationContext
2.AnniocationConfigApplication.getBean
启动spring的过程为:
bean生命周期

1.启动spring
ClassPathXmlApplicationContext  
AnniocationConfigApplication.getBean    

2.扫描
从配置类Appconfig中得到路径
得到Componment注解,得到类

3.懒加载单例bean
扫描出来的信息,进行保存BeanDefination到 CounrrentHashMap<BeanName【@Componment注解中的Value,Bean对象> 中进行过滤
根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿
BeanDefination【类型,Scope[prototype原型Bean,Singleton单例Bean],lazy懒加载机制】 
 
4.创建Bean---> doCreateBean(beanName,BeanDefination)  
先看看单例中有没有吗,没有则创建然后放入到单例池中  
创建单例池的Bean---> CounrrentHashMap(bean,beanDefination)

5.一、实例化
beanDefination.getBeanClass()
反射得到Bean,返回对象。
Bean容器利用java 反射机制实例化Bean

6.二、属性赋值
beanClass.getDeclaredFields()遍历属性,看看有什么属性
field.set()赋值
	若Bean实现了BeanNameAware接口,调用setBeanName()方法
	若Bean实现了BeanClassLoderAware接口,调用setBeanClassLoder()方法
	若Bean实现了BeanFactoryAware接口,则执行setBeanFactory方法
	如果Bean实现了ApplicationContextAware接口,则执行setApplicationContext方法;
    // 相当于切面,初始化之前,初始化之后  做什么事情
    如果加载了BeanPostProcessor相关实现类,则执行postProcessBeforeInitialization方法;
    
7.如果Bean实现了InitializingBean接口,则执行afterPropertiesSet方法;
    如果Bean定义初始化方法(PostConstruct注解或者配置的init-method),则执行定义的初始化方法;
    如果加载了BeanPostProcessor相关实现类,则执行postProcessAfterInitialization方法;
    
8.当要销毁这个Bean时,如果Bean实现了DisposableBean接口,则执行destroy方法。

在这里插入图片描述

在这里插入图片描述

1.3 Spring循环依赖

文章核心:spring循环依赖细节总结
循环依赖细节总结
在这里插入图片描述

在这里插入图片描述

一级缓存:缓存最终的单例池对象: 
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
二级缓存:缓存初始化的对象:
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
三级缓存:缓存对象的ObjectFactory: 
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

1.4 二级缓存就已经解决了循环依赖了,为神魔需要三级缓存?

一个缓存其实就是两个Map,A B 就能解决问题了
正常的场景一般没有问题,有什么特殊场景会有问题?

  在上面第5步里面,Bean的后置处理器BeanPostProcessor,可能会进行AOP
  	  1.如果配置了切面AOP才会进行AOP,AOP底层是采用动态代理实现的【JDK CGLIB】
  	  2.AOP会生成一个代理对象,一个原始对象,一个代理对象,肯定会把代理对象放入到单例池中
  	  3.在原始对象赋值的时候,执行完毕后,代理对象放入后会发生冲突,而B属性是原始对象  
  问题解决:
  	  1.一个原始对象,一个代理对象,AOP提前进行,在原始对象之后就进行生成代理对象,全部都是代理对象了
  	  原始对象--->AOP--->代理对象--->放入缓存Map    没有问题了

1.5 Bean对象和创建的对象有什么区别?

// UserService 里面有一个User属性
UserService userService = context.getBean("userService",UserService.class); // 单例决定
UserService userService2 = new UserService();

1.引用地址不同
2.Bean里面的User是有值的【自动填充属性】,而new出来的是没有的

1.6 BeanDefination是什么?

BeanDefination【ByType、ByName类型,Scope[prototype原型Bean,Singleton单例Bean], lazy懒加载机制】

3.懒加载单例bean
扫描出来的信息,进行保存BeanDefinationCounrrentHashMap<BeanName@Componment注解中的Value,Bean对象> 中进行过滤
根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿

4.创建Bean---> doCreateBean(beanName,BeanDefination)  
先看看单例中有没有吗,没有则创建然后放入到单例池中  
创建单例池的Bean---> CounrrentHashMap(bean,beanDefination)

1.7 什么是 BeanPostProcessor 后置处理器?

等待组件初始化完成,后置处理器才会工作
1.如BeanFactoryPostProcessor 操作BeanFactory
2.包扫描,扫到@Component后,就会生成BeanDefination定义

BeanFactoryPostProcessor
BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应⽤:PropertyPlaceholderConfigurer(属性替换符),此接⼝只提供了⼀个⽅法

1.其中有个⽅法名为getBeanDefinition的⽅法,我们可以根据此⽅法,找到我们定义bean 的BeanDefinition对象。然后我们可以对定义的属性进⾏修改,以下是BeanDefinition中的⽅法

2.⽅法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以⼿动修改bean标签中所定义的属性值。

1.8 BeanFactory与ApplicationContext的区别?

ApplicationContext是BeanFactory的一种实现
通常情况,BeanFactory 的实现是使用懒加载的方式,这意味着 beans 只有在我们通过 getBean() 方法直接调用它们时才进行实例化实现 BeanFactory 最常用的 API 是 XMLBeanFactory

public class HelloWorldApp {
    
    
        public static void main(String[] args) {
    
    
            XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
            HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
            obj.getMessage();
        }
    }

ApplicationContext 接口

ApplicationContext 是 Spring 应用程序中的中央接口,用于向应用程序提供配置信息它继承了 BeanFactory 接口所以 ApplicationContext 包含 BeanFactory 的所有功能以及更多功能!它的主要功能是支持大型的业务应用的创建特性:
Bean instantiation/wiring

Bean 的实例化/串联

自动的 BeanPostProcessor 注册

自动的 BeanFactoryPostProcessor 注册

方便的 MessageSource 访问(i18n)

ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化

public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
        obj.getMessage();
    }

1.9 BeanFactory 与 FactoryBean的区别??

BeanFactory
这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等

getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象
containsBean(String name)Spring容器中是否存在该对象
isSingleton(String name):通过beanName是否为单例对象
isPrototype(String name):判断bean对象是否为多例对象
isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配
getType(String name):获取BeanClass类型
getAliases(String name):获取name所对应的所有的别名

使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象

FactoryBean
该类是SpringIOC容器是创建Bean的一种形式,这种方式创建Bean会有加成方式,融合了简单的工厂设计模式于装饰器模式

T getObject():返回实例
Class<?> getObjectType();:返回该装饰对象的Bean的类型
default boolean isSingleton():Bean是否为单例

区别:

BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范,
FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其可封装对象的创建细节。

Supongo que te gusta

Origin blog.csdn.net/wyn_365/article/details/121222652
Recomendado
Clasificación