spring框架之ioc

概念

ioc容器是具有依赖注入功能的容器,负责对象的实例化、初始化、对象和对象之间依赖关系处理、对象的销毁、提供对象查找等操作,对象的整个生命周期都是由容器来控制。

我们需要使用的对象都是由ioc容器进行管理,直接从容器中获取即可,不需要通过手动new的方式去创建对象了。

ioc容器支持两种配置

  1. xml文件格式。(ClassPathXmlApplicationContext)
  2. java注解方式。(AnnotationConfigApplicationContext)

 

关于Bean的生命周期请参考:https://blog.csdn.net/sumengnan/article/details/113702527

 

(1)关键的接口(扩展点)

1、BeanDefinition

表示bean定义信息的接口,里面定义了一些获取bean定义配置信息的方法。

实现类包括

  1. RootBeanDefinition:根bean定义信息。表示没有父bean的bean
  2. ChildBeanDefinition:子bean定义信息。需要通过parentName属性来指定父bean
  3. GenericBeanDefinition:通用bean定义信息。既可以表示没有父bean的bean,也可以表示有父bean的子bean信息。也有parent属性。
  4. ConfigurationClassBeanDefinition:配置类中@bean方法定义的bean信息。
  5. AnnotatedGenercBeanDefinition:通过注解方式定义的bean信息。AnnotationMetadata getMetadata()用来获取定义这个bean的类上的所有注解信息。

BeanDefinitionDefaults:是个类。表示对bean的默认简单持有
BeanDefinitionHolder:是个类。表示对bean的持有(加一层包装),同时包括对bean的名称和别名

BeanDefinitionBuilder是个工具类内部提供了许多静态方法,通过这些方法可以组装BeanDefinition对象。

2、BeanDefinitionReader

将各种方式定义的bean信息解析成BeanDefinition,如xml方式、properties方式、注解方式。

常用的实现类包括:

  1. XmlBeanDefinitionReader:
  2. PropertiesBeanDefinitionReader:
  3. ConfigurationClassBeanDefinitionReader

XmlbeanDefinitionReader的loadBeanDefinitions方法最终通过DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法完成解析

PropertiesBeanDefinitionReader的registerBeanDefinition方法中完成BeanDefinition的解析和注册

其他:

ClassPathBeanDefinitionScanner是一个bean定义的自动扫描类,可以通过scan方法,自动扫描并注册beanDefinition

ConfigurationClassBeanDefinitionReaders是一个用于读取@configuration注解的类,并交给ConfigurationClassParser解析

3、BeanDefinitionRegistry

此接口用于bean定义的注册

例如:BeanFatory实现了bean定义注册器接口,就具有了registerBeanDefinition方法(注册bean的功能)

4、BeanDefinitionParser

用来解析命名空间下bean定义标签。比如 context 命名空间下的  component-scan , 对应 ComponentScanBeanDefinitionParser 

5、ImportSelector

用于spring导入外部配置的核心接口。例如springboot的自动化配置和@EnableXXX(功能性注解)都有它的存在

实现类如下:

其他:

ConfigurationClassParser是一个用来解析被@Configuration

BeanFactory 实现类是DefaultListableBeanFactory

applicationContext 实现类是AnnotationConfigServletWebServerApplicationContext(当我们使用springboot并且是sevlet环境时)

(2)关键的后置处理器接口(扩展点)

1、BeanPostProcessor

可以对bean“实例化”前或后进行自定义处理操作。被调用处代码如下

2、BeanFactoryPostProcessor

可以在bean创建之前,修改bean的定义属性,执行顺序在BeanDefinitionRegistry之后

3、BeanDefinitionRegistryPostProcessor

继承自BeanFactoryPostProcessor。在所有的beanDefinition信息将要被加载,bean实例还未创建的时候执行。可以给容器中额外再增加一些组件。

在AbstractApplicationContext类的invokeBeanFactoryPostProcessors方法(PostProcessorRegistration使用了Delegate委派设计模式),代码位置如下:

执行顺序在BeanFactoryPostProcessor之前

其他:

ConfigurationClassPostProcessor是一个对@Configuration注解做处理的类。处理完毕后通过BeanDefinitionRegistry注册此bean。

4、InstantiationAwareBeanPostProcessorea

用于bean的“初始化”阶段前后

5、DestructionAwareBeanPostProcessor

继承BeanPostProcessor用于bean销毁时的操作

 

6、SmartInstantiationAwareBeanPostProcessor

实现类如下:

实现类之AutowiredAnnotationBeanPostProcessor

扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去

AbstractAutoProxyCreator实现类:spring框架在初始化bean时,如果需要aop,则使用实现类,通过ProxyFactory(spring对两种动态代理的封装)类实现。

 

7、ApplicationListener (应用监听器)

当我们的类实现了ApplicationListener接口中的onApplicationEvent方法,只要当ApplicationEvent被发布后触发。所以我们可以自定义类对任何阶段的事件进行处理。

spring默认有四种事件。

例如:当应用上下文执行start方法后会发布ContextStartedEventEvent事件

完成Refresh刷新时执行:

关闭容器时:

8、Lifecycle (生命周期接口)

实现类是:DefaultLifecycleProcessor

所有的容器都有生命周期,需要实现此接口。例如:ApplicationContext。如下图:

9、AutowireCandidateResolver(自动注入候选解析接口)

用于确定特定的Bean定义是否符合特定的依赖项的候选者的策略接口。用来解析@Autowired、@Primary、@Qualifier、@Value、@Lazy等注解

  • ContextAnnotationAutowireCandidateResolver 是用来处理@Lazy注解的,如果是lazy则生成代理类
  • QualifierAnnotationAutowireCandidateResolver  是用来处理@Autowired、@Primary、@Qualifier、@Value等注解的

 

(4)bean接口(扩展点)

factoryBean:实现了该接口的bean,需要手动实现getObject方法返回bean(相当于在bean中使用工厂模式)

InitializingBean:实现了该接口的bean,在bean的属性注入完成后执行此afterPropertiesSet方法

init-method:bean的初始化方法,在InitializingBean之后执行。可以在xml中bean的init-method或@bean注解的属性使用

DisposableBean:实现了该接口的bean,在bean被销毁时会执行destroy方法

Aware接口(扩展点)

Aware翻译过来意思是感知的、察觉到。

当一个bean实现了Aware的接口时,它就可以获得某种spring组件。

Aware的子接口如下:

每种子接口都可以获得一种组件,根据命名可以大致看出。

例如:实现BeanFactoryAware接口的bean,实现setBeanFactory方法,参数为beanfactory。spring底层实例化bean时,会通过此方法把beanfactory传给此bean。

Capable

翻译过来是能力的意思。和Aware相反。表示具有某种能力。

例如:EnvironmentCapable接口:实现了此接口的类有能力提供Environment环境,具有getEnvironment方法。

当spring需要Environment环境时,会通过getEnvironment方法向你要。

 

常见问题

1、循环依赖问题

使用了三级缓存解决

 

2、beanFactory和factoryBean区别?

beanfactory:bean工厂。是spring最顶级的核心接口,负责bean的生产、获取

factoryBean:区别于普通的bean,factoryBean接口包含getObject()方法。相当于在bean中使用工厂模式获取自定义的bean。

如果通过BeanFactory获取FactoryBean本身时,需要加上&符号。

factorybean通常用来创建复杂的bean(如mybatis的SqlSessionFactory)一般bean直接xml配置即可,但如果过程太复杂则直接使用FactoryBean更简单。

 

3、BeanFactory和ApllicationContext区别?

beanfactory:bean工厂。是spring最顶级的核心接口,负责bean的生产、获取。(通过延迟加载来注入Bean)。

applicationcontext:应用上下文。继承了Beanfactory接口,除了包含beanfactory基本的功能外。(在IOC启动时创建所有的bean,好处是可以马上发现配置文件的错误,坏处是浪费资源)

由于也继承了其他接口如:MessageSource、ResourceLoader、applicationEventPulisher。

而增加了国际化、访问资源文件、发送事件机制等功能。如图:

 

4、spring配置bean实例化有几种方式

  1. 通过反射调用构造方法
  2. 通过静态工厂方法
  3. 通过实例工厂方法
  4. 通过FactoryBean创建
//反射调用构造方法
<bean id="bean名称">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
</bean>
//静态工厂方法
<bean id="bean名称" class="静态工厂完整类名" factory-method="静态工厂的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
</bean>
//实例工厂方法
<bean id="bean名称" factory-bean="需要调用的实例对象bean名称" factory-method="bean对象中的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
</bean>
//实现了FactoryBean的类
<bean id="bean名称" class="FactoryBean接口实现类" />

5、spring是如何处理线程并发问题的?

首先我们要知道解决线程并发问题有两种方式:

  1. 线程同步机制(加锁):好处是使用简单。但是会有性能问题。采用了“时间换空间”的方式
  2. 使用ThreadLocal类:在jdk1.2之后提供此类。采用了“空间换时间”的方式。(spring使用的就是这种方法,对一些非线程安全的状态bean封装。例如:LocaleContextHolder、RequestContextHolder)

ThreadLocal类会为每个线程提供一个独立的变量副本(就是复制变量到线程本地),从而隔离多个线程对同一数据的访问冲突。因为每个线程都拥有自己的变量副本,使用线程本地变量即可,不用调用共享变量,也就不存在线程安全问题了。

所以我们在平时编写多线程代码时,也可以使用ThreadLocal类把不安全的变量封装进ThreadLocal中。例如:SimpleDateFormat类。

 

6、spring中使用了哪些设计模式?

sping IOC模块:

  • 工厂模式:BeanFactory
  • 装饰器模式:BeanWrapper
  • 单例模式:ApplicationContext
  • 代理模式:AopProxy

spring AOP模块

  • 代理模式:AopProxy
  • 观察者模式:ContextLoaderListener

spring MVC模块

  • 委派模式:DispatcherServlet
  • 策略模式:HandlerMapping
  • 适配器模式:HandlerAdapter

Spring JDBC模块

  • 模版模式:JdbcTemplate

 

7、spring中有哪些类型的事件?

只有4种:

  1. 上下文更新事件(ContextRefreshedEvent):调用ConfigurableApplicationContext接口的refresh方法时触发
  2. 上下文开始事件(ContextStartedEvent):调用ConfigurableApplicationContext接口的start方法开始或重新开始容器时触发
  3. 上下文停止事件(ContextStoppedEvent):调用ConfigurableApplicationContext接口的stop方法时触发
  4. 上下文关闭事件(ContextClosedEvent):当applicationContext被关闭时触发。容器被关闭时,其管理的所有单例bean都被销毁

上面只是spring中的事件。

其他实现了ApplicationEvent接口的类,如图:

其中也包括springboot的SpringApplicationEvent、ApplicationStartingEvent等事件。

如何接收处理这些事件?

当我们的类实现了ApplicationListener接口中的onApplicationEvent方法,只要当ApplicationEvent被发布后触发。所以我们可以自定义类对任何阶段的事件进行处理。

ApplicationListener接口的实现类如下:

实现spring事件监听有哪两种方式?

  1. 上面说的实现ApplicationListener接口
  2. 使用@EventListener注解的方法

处理被注解的方式使用的类是:EventListenerMethodProcessor,在bean周期的第十步被解析成ApplicationListener类型的数据,方法入AbstractApplicationContext类的applicationListeners Set集合中。

反射调用被注解的方法使用的类是:ApplicationListenerMethodAdapter

 

8、spring事务实现有哪几种方式?

请参考:https://blog.csdn.net/sumengnan/article/details/112639564

  1. 编程式事务 :使用PlatformTransactionManager编程事务接口,或使用TransactionTemplate模版类(实际是PlatformTransactionManager的封装)
  2. 注解式事务:xml配置aop或tx命名空间,或直接使用@Transaction注解

9、spring中bean的几种作用域?

  1. singleton:单例。IOC容器中仅存在一个Bean实例。
  2. prototype:原型模式。每次从容器中获取bean时,都返回一个新的实例。(注意使用@Autowired注入的bean只会注入一次)
  3. request:在web环境中,每次http请求都会创建一个新的bean。
  4. session:在web环境中,同一个http session共享一个bean。
  5. application:在web环境中,bean的作用域为ServletContext的生命周期。

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值