spring

基础概念:

1、IoC 和 DI

IoC (Inversion of Control),即控制反转。是 Spring 的一种设计思想。

在传统的程序设计,我们直接在对象内部通过 new 来创建对象,是程序主动去创建依赖对象;而在 Spring 中有专门的一个容器来创建和管理这些对象,并将对象依赖的其他对象注入到该对象中,这个容器我们一般称为 IoC 容器。

所有的类的创建、销毁都由 Spring 来控制,也就是说控制对象生存周期的不再是引用它的对象,而是 Spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被 Spring 控制,所以这叫控制反转。

DI(Dependency Injection),即依赖注入,由 Martin Fowler 提出。可以认为 IoC 和 DI 其实是同一个概念的不同角度描述。

依赖注入是指组件之间的依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。

通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

2、bean

官方概念:在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。 bean 是一个由 Spring IoC 容器实例化,组装和管理的对象。

大白话:bean 可以认为是那些我们想注入到 Spring IoC 容器的 Java 对象实例的抽象。

我们经常会在 Service 上使用 @Service 注解,然后在要使用该 Service 的类中通过 @Autowire 注解来注入,这个 Service 就是一个 bean。在这个地方,@Service 注解相当于告诉 IoC 容器:这个类你需要帮我创建和管理;而 @Autowire 注解相当于告诉 IoC 容器:我需要依赖这个类,你需要帮我注入进来。

3、BeanDefinition

理解了 bean,BeanDefinition 就好理解了。BeanDefinition 是 bean 的定义,用来存储 bean 的所有属性方法定义。

4、BeanFactory 和 ApplicationContext

BeanFactory:基础类型 IoC 容器,提供完整的 IoC 服务支持。

ApplicationContext:BeanFactory 的子接口,在 BeanFactory 的基础上构建,是相对比较高级的 IoC 容器实现。包含 BeanFactory 的所有功能,还提供了其他高级的特性,比如:事件发布、国际化信息支持、统一资源加载策略等。正常情况下,我们都是使用的 ApplicationContext。其还有个重要特性就是ApplicationContext不是懒加载的。

5、FactoryBean

一般情况下,我们将 bean 的创建和管理都交给 Spring IoC 容器,Spring 会利用 bean 的 class 属性指定的类来实例化 bean。

但是如果我们想自己实现 bean 的创建操作,可以实现吗?答案是可以的,FactoryBean 就可以实现这个需求。

FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法即可。

spring的ioc的容器bean的refresh过程。。说实话代码复杂流程长(12个方法。。。)。看个七八遍能看出主干流程就不错了。。

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 设置容器状态,启动时间,状态激活等
		prepareRefresh();

		// 创建bean工厂,如果已经有老的则把老的干掉,默认创建的是DefaultListableBeanFactory
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// bean工厂投入生产前的各种配置,如bean定义器、加载器,后置处理器注册环境相关的默认bean到单例缓存map中等
		prepareBeanFactory(beanFactory);

		try {
			// 工厂后置处理器默认空实现 在通过方法prepareBeanFactory执行了标准的初始化之后来修 
           //改内部的bean factory。此时所有的bean definition都已经加载完毕但是没有任何的bean完 
            //成初始化。
			postProcessBeanFactory(beanFactory);

			// 应用BeanFactoryPostProcessor
            //在bean definition加载完毕后,在通过bean definition生成bean之前,
			//调用BeanFactoryPostProcessor,在这里可以随意修改所有用户bean的定义
			invokeBeanFactoryPostProcessors(beanFactory);


			// 实例化和注册BeanPostProcessor,bean的后置处理器,初始化前后进行处理工作
			registerBeanPostProcessors(beanFactory);

			// 初始化MessageSource,辅助i18n
			initMessageSource();

			// 初始化上下文的时间广播器。event
			initApplicationEventMulticaster();

			// 空实现。目前啥也没干
			onRefresh();

			// 注册监听器
			registerListeners();

			// 初始化非延迟加载的单例bean
			finishBeanFactoryInitialization(beanFactory);
			// 完成刷新
			finishRefresh();
		}

1、ioc流程

1.准备阶段,设置一些容器的参数,状态。

2.创建beanFactory,DefaultListableBeanFactory.接着配置,如bean定义器、加载器,后置处理器此时所有的bean definition都已经加载完毕但是没有任何的bean完成初始化

3、应用BeanFactoryPostProcessor,在在beandefinition加载完毕后,beanDefinition加载bean之前,通过BeanFactoryPostProcessor可以自定义修改对象

4、实例化和注册BeanPostProcessor,bean的后置处理器

5、通过反射将beanDefinition对象实例化成bean对象

5、初始化广播器注册监听器

6、初始化对象,填充对象属性,执行beanPostProcessor,init-mehtod方法。

7、生成完整的bean对象后,调用getbean对象获取对象

8、对象销毁

bean的生命周期:首先,bean的生命周期就是 实例化,属性注入,初始化,销毁

解决循环依赖问题:java的引用传递(对象的属性可以延迟设置)和三级缓存

/** 一级缓存,缓存初始化完成的单例对象,放到这里的单例对象是可以直接使用的 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 二级缓存,缓存提前曝光的单例对象,放到这里的单例对象是不完整的*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** 三级缓存,缓存可以创建bean的工厂,ObjectFactory是一个生产者函数式接口,
    实现这个接口的lambda表达式提供一个创建bean的方法*/ 
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
 

1、通过提前曝光实例化的bean(执行bean的构造方法),解决循环依赖,因此构造器注入的bean循环依赖无法解决。此时构造器都还没执行,还没有实例化对象的引用

2、多例模式的bean不使用缓存,循环依赖叶无法解决

3、A在实例化之后放入三级缓存;当B注入属性A时,A从三级缓存升级到二级缓存(A此时尚不完整),A完成初始化之后升级到一级缓存。B在实例化之后放入三级缓存;在初始化之后升级到一级缓存

4、3级缓存解决代理对象的循环依赖。

 aop:aop其实是beanPostProssed 的一个拓展点,是bean后置处理器里的执行逻辑。

通过 DefaultAopProxyFactory 调用createAopProxy来创建代理对象放入到ioc容器。其和 原对象具有相同给的hashCode值,但是不同的内存地址。create是通过一组jvm指令集获取源对象的字节码进行修改生成的代理对象,jdk动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。需要实现其invok方法。使用cglib必须要用接口的原因就是public class $Proxy1 extends Proxy implements xxxxx  代理类受限于java单继承的语法限制。

事务@Transaction

在开启事务@EnableTransaction注解的时候实际上是注入了三个类:

TransactionIntercetor:用于拦截方法,事务的创建提交回滚等

TransactionInAttributeSourcePoint: 用作方法匹配,

TransactionAttributeSource:解析事务的属性,并且缓存

1、实例化事务拦截器TransactionIntercetor、事务属性解析器TransactionAttributeSource 以及增强器 BeanFactoryTransactionAttributeSourceAdvisor

2、先调用增强器接口找出所有的advisors

3、然后找到自己的增强器后反射获取所有的类方法,并且匹配哪些方法有事务注解,先查混缓存,如果没有则解析事务注解缓存起来

4、根据这个事务注解类创建代理对象。

注解无效情况:

获取事务属性时判断了方法是否ispublic。不是public事务无效

同类中调用或者catch异常或者是事务传播行为设置错误

事务传播行为默认:当前事务存在则加入,不存在创建。  还有存在则加入,不存在则不用事务、抛异常等

总结:

ioc容器初始化过程

1、设置容器的一些状态和参数

2、创建ioc容器,默认使用DefaultListableBeanFactory创建bean工厂。并且配置Bean的定义,加载器以及后置处理等。此时Bean Definition 以及加载但是未初始化

3、应用factory处理器,在在通过Bean Definition生成bean之前,通过BeanFactoryPrecess可以对bean Definition进行修改

4、通过Bean Definition 用反射实例化成Bean对象

5、初始化和注册event监听器

6、初始化Bean对象,实例化和注册BeanPostProcess。执行器后置方法,bean的init方法等

7、生成完成的bean对象。此时可以调用getBean获取对象。

bean生命周期严格讲 初始化--属性注入--调用Aware方法--BeanPostProcess前置处理器方法--初始化方法--BeanProcess后置处理方法--Bean完成初始化可以使用--容器关闭调用destory方法--自己定义的销毁方法--over

Aop其实说白了,是spring ioc 里面 beanPostProcess的一个扩展点,是bean后置处理器里的延伸逻辑。在beanPostProcess的后置处理方法里,最终是通过DefaultAutoProxyFactorycreateAopProxy来创建代理对象放入到ioc容器中,所以原始对象并不会出现在容器中。jdk动态代理依靠反射生成一个匿名内部类,在执行方法前调用invokerHandl来处理。而cglib动态代理则通过集成Proxy类,通过在家原始类的字节码进行修改而生成的新的代理对象,因其已经实现了Proxy类,因此代理对象必须是接口才能符合java的语法规范。

spring事务也是基于动态代理来实现的。当我们使用@EnableTrantsaction注解时实际上是网容器里注册了三个类:@TrantsactionIntercetor:用于拦截标的方法,@TransactionAttributeSoucePoit:方法的匹配,也就是要拦截哪些方法。@TransactionAttribute 解析事务注解属性,并缓存

通过拦截,解析然后生成事务注解类的代理对象,在增强方法里进行事务控制。

其中注意aop在同类中调用方法将不生效,事务注解对是否是public方法进行了判断,非public方法无效。

springboot的类自动装配spi机制实现是其会自动加载mat-info下spring.factories文件中配置的类形象autoCofig,其最终还是会调用ioc容器舒适化方法,通过其将自动配置类放入到ioc容器中区。

其内置tomcat启动也是通过将Enviroment、profile等配置注入到Server。然后将ServletWebServerApplicationContext内通过onFresh方法注册进去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值