Java -- Spring

一、Spring简介

1. 概述

  • Spring是一个轻量级Java开发框架(最早由Rod Johnson创建),为Java应用程序提供全面的基础架构支持。
  • Spring最根本的使命是解决企业级应用开发的复杂性,简化Java开发。

2. Spring两个核心特性

IoC(Inverse of Control)–> 控制反转

  • IoC理念:
    1. 对象的创建工作交给IoC容器
    2. 对象间的依赖关系交给IoC容器查找,在运行期间确定
    3. 依赖注入是IoC的主要实现方式
  • IoC的实现机制:
    工厂模式 + 反射机制:工厂模式提供创建方法,通过反射获取需要加载的类的全限定名称,通过工厂加载产生需要的类对象。

AoP(Aspect Oriented Programing) --> 面向切面编程

  • AoP理念:通过预编译/运行时动态代理的方式,将那些与业务无关但对多个对象产生影响的公共行为(如日志、事务等),抽取并封装成可重用的模块 --> “切面
  • Spring中AoP提供声明式事务,允许用户自定义切面

二、IoC详解

1. 核心容器

  • 容器提供了IoC功能,BeanFactory和ApplicationContext都是容器
容器类型作用加载方式
BeanFactory低级容器:功能少懒加载,用到实例才加载
ApplicationContext高级容器:功能多预加载,容器启动时一次性加载
  • 总结:

① ApplicationContext是BeanFactory的子接口,在基本功能之上提供了更多的功能:

  1. 继承了MessageSource,支持国际化
  2. 提供统一的资源访问方式
  3. 同时加载多个配置文件,可载入上下文(具有层级关系)

② BeanFactory为低级容器,类似于Map(Key --> BeanName,Value --> Bean实例),BeanFactory只提供最简单的注册(put)和获取(get)两个功能
③ ApplicationContext为高级容器,继承多个接口,功能强大

2. ApplicationContext常见实现

① FileSystemXmlApplicationContext:全路径名找Xml
② ClassPathXmlApplicationContext:在ClassPath中找Xml
③ WebXmlApplicationContext:一般从RequestContextUtils中获取Xml

3. DI(Dependency Injection)依赖注入

  • DI依赖注入是IoC控制反转的重要实现方式
  • 注入方式(3钟)

① Xml配置:

  1. 接口注入:灵活性差,易用性差,Spring4后弃用
  2. 构造器注入:全属性注入,任何改动会导致新实例的创建<constructor-arg name="" value=""/)
  3. Setter方法注入:部分/全属性注入,改动不会导致新实例的创建 <property name="" value=""/)

② 注解配置(将类对象托管给容器)

  1. @Component(“BeanName”) --> 可显示地指定BeanName,若不指定则按照类名驼峰命名
    衍生出@Controller + @Service + @Repository/@Mapper
  2. 在属性上方@Value可以直接对该属性赋值

③ Java配置

  1. @Configuration + @Bean
  2. @Bean在方法上使用,方法返回值作为JavaBean被托管到容器中

4. JavaBean作用域(Scope)

① SingleTon:单例模式(默认),每次返回的实例为同一个,适用于无状态的JavaBean
② ProtoType:原型模式,每次返回一个新的JavaBean,适用于有状态的JavaBean
③ Web应用中:

request:为每一个请求创建一个实例
session:同一个session会话共享一个实例,不同会话使用不同实例
global-session:全局作用域,所有session会话共享一个实例

5. Bean的装配机制

  • ① Xml中显示装配(ref)
  • ② Java代码中显示装配 @Configuration + @Bean
  • ③ 自动装配
  1. 自动装配主要分为两种:byName和byType,可在xml中加入autowire=byName/byType来指定自动装配方法
  2. @Autowired自动装配:先按照byType装配,若对应type的对象有多个,则按照类名驼峰命名的名字进行byName装配
  3. @Qualifier(“BeanName”):指定具体JavaBean名,进行byName加载;主要是作为@Autowired的补充修饰,消除歧义
  4. @Resource:先按照byName进行装配,然后按照buType装配

6. Bean的生命周期

  • 简单来说分为四个阶段:
    • 实例化 Instantiation
    • 属性赋值 Populate
    • 初始化 Initialization
    • 销毁 Destruction

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5s08on6a-1626181763936)(http://182.92.190.128:8090/upload/2021/07/image-a4e39ff9b3a54e44828f6be6b7e39ca7.png)]

(1)实例化Bean:

  • 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
  • 对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。

(2)设置对象属性(依赖注入):

  • 实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成属性设置与依赖注入。

(3) InitializingBean:

  • 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。

(4) destroy-method:

  • 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
  • 详细的生命周期形成过程在后面的源码解析中!

三、AoP详解

1. SpringAop名词解释

① 切面(Aspect):由通知 + 切点组成
② 连接点(Join Point):能够插入切面的点
③ 通知(Advice):切面的逻辑(工作内容)
④ 切点(PointCut):切点的定义用于匹配通知所要织入的连接点
⑤ 引入(Introduction)
⑥ 目标对象(Target):被切面通知的对象
⑦ 织入(Wearing):切面插入,创建新代理对象
image.png

2. 通知类型

  1. Before
  2. After
  3. Around
  4. AfterReturning
  5. AfterThrowing

3. SpringAoP 和 AspectJAoP

  • AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表;而动态代理则以 Spring AOP 为代表
  • Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
类型原理织入对象局限
AspectJAoP静态代理增强,切面逻辑织入字节码编译/类加载期间生成AoP代理类,织入颗粒度更细性能更好,但需要特定编译器
JDK动态代理JDK动态代理,不修改字节码为方法生成代理对象,方法级别的连接点只能代理接口
Cglib动态代理字节码生成,通过继承方式实现代理运行时生成子类,覆盖特定方法并添加增强代码final类无法代理
  • 注意:
    • JDK动态代理只提供接口的代理,不支持类的代理,核心为InvocationHandler接口和Proxy类
    • 如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类;
    • CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的

四、Spring容器的启动流程

1. 总体流程

  1. 初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中
  2. 将配置类的BeanDefinition注册到容器中
  3. 调用refresh()方法刷新容器
  • 调用构造方法,初始化容器:
    • AnnotationConfigApplicationContext是注解注入
    • ClassPathXmlApplicationContext 是xml注入
    • 我们调用的是有参的构造方法,有参构造方法中会自动调用无参构造方法this()进行操作
  • AnnotationConfigApplicationContext和ClassPathXmlApplicationContext 都继承自AbstractApplicationContext ,其中定义了refresh()方法
// 初始化容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {

    this();				// 1. 注册 Spring 内置后置处理器的 BeanDefinition 到容器
    
    register(annotatedClasses);		// 2. 注册配置类 BeanDefinition 到容器
    
    refresh();				// 3. 加载或者刷新容器中的Bean
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-samvvSU8-1626181763939)(http://182.92.190.128:8090/upload/2021/07/image-ff5602dda5ce4f70b56d6f22ed2ab112.png)]

2. 初始化流程

(1) 无参构造函数this()

  • 主要完成以下三项工作
  1. 实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
  2. 实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
  3. 实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象
// 无参构造方法	
public AnnotationConfigApplicationContext() {					// 实例化Spring容器
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		this.reader = new AnnotatedBeanDefinitionReader(this);		// 实例化配置读取器
		createAnnotatedBeanDefReader.end();
		this.scanner = new ClassPathBeanDefinitionScanner(this);	// 实例化路径扫描器
	}

(2) 内置组件添加

  • 调用无参构造函数this()完成后,Spring容器已经构造完毕,这时需要为容器添加一些内置组件

  • 调用方法:org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors

  • 主要组件:

    • ConfigurationClassPostProcessor:beanFactory后置处理器,用来完成 bean 的扫描与注入工作
    • AutowiredAnnotationBeanPostProcessor:bean后置处理器,用来完成 @AutoWired 自动注入
  • 源码跟踪:

    • 容器有参构造 --> this()无参
    • new AnnotatedBeanDefinitionReader(this) --> 构造方法中调用
    • AnnotationConfigUtils --> registerAnnotationConfigProcessors() 方法添加内置组件
  • 构造方法源码:渐进调用

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	Assert.notNull(environment, "Environment must not be null");
	this.registry = registry;
	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);	// 内置组件添加
}	
  • 内置组件添加源码:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
	BeanDefinitionRegistry registry, @Nullable Object source) {

	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	if (beanFactory != null) {
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
	
	// 向beanDefinitionMap中注册BeanFactoryProcessor:ConfigurationClassPostProcessor
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	
	// 向beanDefinitionMap中注册BeanPostProcessor:AutowiredAnnotationBeanPostProcessor
	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	// 向beanDefinitionMap中注册BeanPostProcessor:CommonAnnotationBeanPostProcessor
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	// 向beanDefinitionMap中注册BeanPostProcessor:PersistenceAnnotationBeanPostProcessor
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}

	return beanDefs;
}

(3) 注册SpringConfig配置类到容器中

  • 源码跟踪

    • 容器初始化构造方法中的register(componentClasses)方法
    • 调用this.reader.register(componentClasses)
    • registerBean(componentClass) --> doRegisterBean(beanClass , …)
  • doRegisterBean源码分析:

      1. 解析用户传入的Spring配置类
      1. 将配置类封装成一个BeanDefinition注册到容器中
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                                @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
                                @Nullable BeanDefinitionCustomizer[] customizers) {

    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(supplier);
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

(4) refresh()容器刷新

  • 源码跟踪:

    • refresh()方法在AbstractApplicationContext这个抽象父类中
  • refresh源码分析:

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 1. 刷新前的预处理
		prepareRefresh();
 
		// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
		// 3. 预处理 beanFactory,向容器中添加一些组件
		prepareBeanFactory(beanFactory);
 
		try {
			// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置
			postProcessBeanFactory(beanFactory);
 
			// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器
			invokeBeanFactoryPostProcessors(beanFactory);
 
			// 6. 注册 BeanPostProcessors,bean 后置处理器
			registerBeanPostProcessors(beanFactory);
 
			// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)
			initMessageSource();
 
			// 8. 初始化事件派发器,在注册监听器时会用到
			initApplicationEventMulticaster();
 
			// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用
			onRefresh();
 
			// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)
			registerListeners();
 
			// 11. 初始化所有的非单实例 bean
			finishBeanFactoryInitialization(beanFactory);
 
			// 12. 发布容器刷新完成事件
			finishRefresh();
		}
		...
	}
}

1. prepareRefresh()刷新前的预处理:
(1)initPropertySources():初始化一些属性设置,子类自定义个性化的属性设置方法;
(2)getEnvironment().validateRequiredProperties():检验属性的合法性
(3)earlyApplicationEvents = new LinkedHashSet():保存容器中的一些早期的事件;

2. obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory:
(1)refreshBeanFactory():刷新BeanFactory,设置序列化ID;
(2)getBeanFactory():返回初始化中的GenericApplicationContext创建的BeanFactory对象,即【DefaultListableBeanFactory】类型

3. prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件:
(1)设置BeanFactory的类加载器、设置表达式解析器等等
(2)添加BeanPostProcessor【ApplicationContextAwareProcessor】
(3)设置忽略自动装配的接口:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware;
(4)注册可以解析的自动装配类,即可以在任意组件中通过注解自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
(5)添加BeanPostProcessor【ApplicationListenerDetector】
(6)添加编译时的AspectJ;
(7)给BeanFactory中注册的3个组件:environment【ConfigurableEnvironment】、systemProperties【Map<String, Object>】、systemEnvironment【Map<String, Object>】

4. postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置

5. invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器
(1)先执行BeanDefinitionRegistryPostProcessor: postProcessor.postProcessBeanDefinitionRegistry(registry)

  • ① 获取所有的实现了BeanDefinitionRegistryPostProcessor接口类型的集合
    ② 先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor
    ③ 再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
    ④ 最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors

(2)再执行BeanFactoryPostProcessor的方法:postProcessor.postProcessBeanFactory(beanFactory)

  • ① 获取所有的实现了BeanFactoryPostProcessor接口类型的集合
    ② 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor
    ③ 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor
    ④ 最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor

6. registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
(1)获取所有实现了BeanPostProcessor接口类型的集合:
(2)先注册实现了PriorityOrdered优先级接口的BeanPostProcessor;
(3)再注册实现了Ordered优先级接口的BeanPostProcessor;
(4)最后注册没有实现任何优先级接口的BeanPostProcessor;
(5)最refresh主要可划分为12个步骤,其中比较重要的步骤下面会有详细说明。Spring 中的每一个容器都会调用 refresh() 方法进行刷新,无论是 Spring 的父子容器,还是 Spring Cloud Feign 中的 feign 隔离容器,每一个容器都会调用这个方法完成初始化。终注册MergedBeanDefinitionPostProcessor类型的BeanPostProcessor:beanFactory.addBeanPostProcessor(postProcessor);
(6)给容器注册一个ApplicationListenerDetector:用于在Bean创建完成后检查是否是ApplicationListener,如果是,就把Bean放到容器中保存起来:applicationContext.addApplicationListener((ApplicationListener<?>) bean);

此时容器中默认有6个默认的BeanProcessor(无任何代理模式下):【ApplicationContextAwareProcessor】、【ConfigurationClassPostProcessorsAwareBeanPostProcessor】、【PostProcessorRegistrationDelegate】、【CommonAnnotationBeanPostProcessor】、【AutowiredAnnotationBeanPostProcessor】、【ApplicationListenerDetector】

7. initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析:
(1)看BeanFactory容器中是否有id为messageSource 并且类型是MessageSource的组件:如果有,直接赋值给messageSource;如果没有,则创建一个DelegatingMessageSource;
(2)把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource;

8. initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到
(1)看BeanFactory容器中是否存在自定义的ApplicationEventMulticaster:如果有,直接从容器中获取;如果没有,则创建一个SimpleApplicationEventMulticaster
(2)将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件就可以直接自动注入

9. onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑

10. registerListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件:
(1)从容器中拿到所有的ApplicationListener
(2)将每个监听器添加到事件派发器中:getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
(3)派发之前步骤产生的事件applicationEvents:getApplicationEventMulticaster().multicastEvent(earlyEvent);

11. finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象
(1)获取容器中的所有beanDefinitionName,依次进行初始化和创建对象
(2)获取Bean的定义信息RootBeanDefinition,它表示自己的BeanDefinition和可能存在父类的BeanDefinition合并后的对象
(3)如果Bean满足这三个条件:非抽象的,单实例,非懒加载,则执行单例Bean创建流程:
(4)所有Bean都利用getBean()创建完成以后,检查所有的Bean是否为SmartInitializingSingleton接口的,如果是;就执行afterSingletonsInstantiated()

12.finishRefresh():发布BeanFactory容器刷新完成事件
1)initLifecycleProcessor():初始化和生命周期有关的后置处理器:默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】,如果没有,则创建一个DefaultLifecycleProcessor()加入到容器;
(2)getLifecycleProcessor().onRefresh():拿到前面定义的生命周期处理器(LifecycleProcessor)回调onRefresh()方法
(3)publishEvent(new ContextRefreshedEvent(this)):发布容器刷新完成事件;
(4)liveBeansView.registerApplicationContext(this);

五、Spring中Bean的加载流程

1. 容器启动阶段

  • 容器的启动阶段做了很多的预热工作,为后面Bean的实例化做好了充分的准备,主要工作有以下5步
    image.png

  • 转载自:Spring中Bean的加载流程

1. 配置元信息:

  • Spring IOC容器将对象实例的创建与对象实例的使用分离,当业务中需要依赖某个对象,不再依靠我们自己手动创建,只需向Spring要,Spring就会以注入的方式交给我们需要的依赖对象。既然将对象创建的任务交给了Spring,那么Spring就需要知道创建一个对象所需要的一些必要的信息。而这些必要的信息可以是Spring过去支持最完善的xml配置文件,或者是其他形式的例如properties的磁盘文件,也可以是现在主流的注解,甚至是直接的代码硬编码。总之,这些创建对象所需要的必要信息称为配置元信息

2. BeanDefination:

  • 在Java世界中,万物皆对象,散落于程序代码各处的注解以及保存在磁盘上的xml或者其他文件等等配置元信息,在内存中总要以一种对象的形式表示,就好比我们活生生的人对应到Java世界中就是一个Person类,而Spring选择在内存中表示这些配置元信息的方式就是BeanDefination,这里我们不会去分析BeanDefination的代码,这里我们只需要知道配置元信息被加载到内存之后是以BeanDefination的形存在的即可。

3. BeanDefinationReader:

  • Spring是如何看懂这些配置元信息的呢?这个就要靠我们的BeanDefinationReader了。不同的BeanDefinationReader拥有不同的功能,如果我们要读取xml配置元信息,那么可以使用XmlBeanDefinationReader。如果我们要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载。而如果我们要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。我们也可以很方便的自定义BeanDefinationReader来自己控制配置元信息的加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination,存在某一个地方,至于这个地方在哪里,不要着急,接着往下看!

4. BeanDefinationRegistry:

  • 执行到这里,Spring已经将存在于各处的配置元信息加载到内存,并转化为BeanDefination的形式,这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?这种通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了
  • Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination

5. BeanFactoryPostProcessor:

  • BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:
<bean id="dataSource"  
    class="org.apache.commons.dbcp.BasicDataSource"  
    destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
  
    <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  
    <property name="url" value="${jdbc.url}"></property>  
  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean> 
  • BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。

2. Bean获取阶段

  • 在容器启动阶段,所有Bean的注册已经完成,接下来通过懒加载/预加载两种方式实例化Bean对象
    • 懒加载:
      Spring只有在第一次依赖对象时才开启相应的实例化阶
    • 预加载:
      容器启动阶段完成之后,其中有一个步骤finishBeanFactoryInitialization(),在这一步将立即启动Bean实例化阶段,通过隐式调用所有依赖对象的getBean()方法来实例化所有配置的Bean,完成类的加载。

(1) Bean的获取(实例化):doGetBean()

doGetBean()的总体功能就是在创建bean对象之前,先去缓存或者beanFactory工厂中查看是否存在bean,如果存在,则返回,不存在,则进行对应的创建流程。

  • 源码阅读:

① 首先调用 ApplicationContext.getBean(“beanName”)获取Bean对象:

applicationContext.getBean("name");

② 然后再调用AbstractApplicationContext.getBean(“beanName”):

public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive(); 
        // 调用getBean 进入AbstractBeanFactory    
        return getBeanFactory().getBean(name);
}

③ 再调用AbstractBeanFactory类下面的doGetBean()方法:

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
 
        /*
        1、转换beanName(别名转换):传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换:
        (1)消除修饰符,比如工厂引用前缀 String FACTORY_BEAN_PREFIX = "&";
        (2)解决spring中alias标签的别名问题
        */ 
		final String beanName = transformedBeanName(name);
		Object bean;
 
        //2、尝试从缓存中去加载实例,如果获取到了就直接返回
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		//如果缓存中存在对应的bean
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			
			//3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。
			// 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
        // 如果缓存中没有对应bean
		else { 
		    //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
 
            // 5、如果缓存中没有数据,就会转到父类工厂去加载
            //获取父工厂
			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			
            //!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
 
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
 
            //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
			try {
                // XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
 
				// Guarantee initialization of beans that the current bean depends on.
				//7、初始化依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				//bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}
 
                //8、创建bean
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
 
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
 
				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
 
		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

(2) 从缓存中获取单例Bean:getSingleton()

  • 在doGetBean()方法中,获取Bean首先会在缓存中查找对应的单例Bean是否存在
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 从缓存池中获取bean:singletonObjects 一级缓
    Object singletonObject = this.singletonObjects.get(beanName);
	
    // 如果一级缓存中为null,再判断是否正在创建
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		// 加锁,防止并发创建
		synchronized (this.singletonObjects) {
			// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
			singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
				// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}
  • 在 Spring 中,bean默认都是单例的,同一个容器的单例只会被创建一次,后续再获取 bean 时,直接从单例缓存 singletonObjects 中进行获取。而且因为单例缓存是公共变量,所以对它进行操作的时候,都进行了加锁操作,避免了多线程并发修改或读取的覆盖操作
  • 还有这里有个 earlySingletonObjects 变量,它也是单例缓存,也是用来保存 beanName 和 创建 bean 实例之间的关系。与 singletonFactories 不同的是,当一个单例 bean 被放入到这 early 单例缓存后,就要从 singletonFactories 中移除,两者是互斥的,主要用来解决循环依赖的问题。

(3) 从实例Bean中获取对象:getObjectForBeanInstance()

  • 在 getBean()/doGetBean()方法中,getObjectForBeanInstance() 是个高频方法,在单例缓存中获得 bean 还是 根据不同的 scope 策略加载 bean,都有这个这个方法的出现。因为从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;		// 如果是nullBean
        }
        if (!(beanInstance instanceof FactoryBean)) {	
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());	// 如果不是工厂Bean也不是空Bean,报错
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        return beanInstance;
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    Object object = null;		// 加载工厂Bean
    if (mbd != null) {
        mbd.isFactoryBean = true;	
    }
    else {
        object = getCachedObjectForFactoryBean(beanName);		// 先从缓存中获取
    }
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;		// 通过工厂getObject方法实例化Bean
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);		// 尝试从单例缓存中获取
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);	// 用户自定义工厂Bean
    }	
    return object;
}

方法功能总结:
(1)验证 bean 类型:判断是否是工厂bean
(2)对非 FactoryBean 不做处理
(3)处理 FactoryBean:如果是FactoryBean类型,先对 bean 进行转换,再委托给 getObjectFromFactoryBean()方法进行处理。

在这个方法中,对工厂 bean 有特殊处理,最终获取的是 FactoryBean.getObject() 方法返回的类型。

(4) 加载单例Bean:getSingleton()

  • 源码:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	// 注释 4.7 全局变量,加锁
	synchronized (this.singletonObjects) {
		//1、再次检查是否已经被加载了,单例模式就是可以复用已经创建的 bean
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			//2、初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			//3、调用createBean方法实例化bean
			singletonObject = singletonFactory.getObject();
			newSingleton = true;
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = null;
			}
			//4、初始化后的操作,移除初始化状态
			afterSingletonCreation(beanName);
			if (newSingleton) {
				//5、加入缓存
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

功能总结:
(1)再次检查缓存是否已经加载过
(2)没有加载,则记录beanName 的加载状态
(3)调用createBean()方法实例化 bean
(4)bean实例化完成之后,移除初始化状态
(5)将实例化结果记录到缓存并删除加载 bean 过程中所记录到的各种辅助状态

  • 对于第(2)步和第(4)步,用来记录 bean 的加载状态,是用来对循环依赖进行检测的。关键的方法createBean(),调用了 ObjectFactory 的 getObject() 方法,实际回调接口实现的是 createBean() 方法进行创建对象(在doGetBean()中)。

3. Bean的实例化阶段:(真正创建对象)

  • 实例化Bean的方法为createBean(),在其中再调用doCreateBean()

(1) createBean()

主要流程:
(1)根据设置的 class 属性或者根据 className 来解析 Class --> resolveBeanClass()
(2)验证及准备覆盖的方法 --> prepareMethodOverrides():这个方法是用来处理以下两个配置的:我们在解析默认标签时,会识别 lookup-method 和 replaced-method 属性,然后这两个配置的加载将会统一存放在 beanDefinition 中的 methodOverrides 属性里。
(3)应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
(4)创建 bean --> doCreateBean()

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;
    

	// 保证bean已经被解析,并且克隆bean定义
    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides. 验证/准备方法覆盖
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
	// 指定解析Bean,让beanPostProcessor有机会返回代理而不是bean实例
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {	// 短路操作,如果代理成功创建Bean,则直接返回
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
	// 创建Bean实例:doCreateBean()
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

(2) prepareMethodOverrides()

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exist and determine their overloaded status.
	if (hasMethodOverrides()) {
		getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
	}
}

// 上述循环中调用
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
	int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
	if (count == 0) {
		throw new BeanDefinitionValidationException(
				"Invalid method override: no method with name '" + mo.getMethodName() +
				"' on class [" + getBeanClassName() + "]");
	}
	else if (count == 1) {
		// Mark override as not overloaded, to avoid the overhead of arg type checking.
		mo.setOverloaded(false);
	}
}

可以看到,获取类的重载方法列表,然后遍历,一个一个进行处理。具体处理的是 lookup-method 和 replaced-method 属性,这个步骤解析的配置将会存入 beanDefinition 中的 methodOverrides 属性里,是为了待会实例化做准备。 如果 bean 在实例化时,监测到 methodOverrides 属性,会动态地位当前 bean 生成代理,使用对应的拦截器为 bean 做增强处理。

(3) resolveBeforeInstantiation()

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    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;
}

在 doCreateBean() 方法前,有一个短路操作,如果后处理器成功,将会返回代理的 bean。

在 resolveBeforeInstantiation() 方法中,在确保 bean 信息已经被解析完成之后,执行了两个关键方法,从注释中看到,一个是前置拦截器的操作,另一个就是后置拦截器的操作。

如果第一个前置拦截器实例化成功,就已经将单例 bean 放入缓存中,它不会再经历普通 bean 的创建过程,没有机会进行后处理器的调用,所以在这里的第二个步骤,就是为了这个 bean 也能应用后处理器的 postProcessAfterInitialization 方法。而如果这个bean没有特定的前置处理,那说明这个bean是一个普通的bean,则按照下面的步骤进行创建

(4) doCreateBean()

整体流程
(1)如果要加载的bean是单例,就先清除缓存中的bean信息
(2)实例化 bean,将 BeanDifinition 转化成 BeanWrapper
(3)后置处理器修改合并后的 bean 定义:bean 合并后的处理,Autowired 注解正式通过此方法实现诸如类型的预解析
(4)依赖处理,提前暴露bean的引用,主要用于解决循环依赖的问题
(5)属性填充:将所有属性填充到 bean 的实例中,如果存在对其他bean的依赖,将会递归初始化依赖的bean
(6)初始化bean:例如afeterPropertiesSet()和init-method属性配置的方法
(7)循环依赖检查
(8)注册 DisposableBean:这一步是用来处理 destroy-method 属性,在这一步注册,以便在销毁对象时调用。
(9)完成创建并返回。

详解:Bean初始化详解

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pulsar-java-spring-boot-starter是一个用于在Spring Boot应用程序中集成Apache Pulsar消息队列的开源库。Apache Pulsar是一个可扩展的、低延迟的分布式消息传递平台,它具有高吞吐量和高可靠性的特点。 pulsar-java-spring-boot-starter允许开发人员在Spring Boot应用程序中轻松地发送和接收Pulsar消息。它提供了一组容易使用的注解和工具类,简化了与Pulsar集群的交互。 使用pulsar-java-spring-boot-starter,开发人员可以通过添加依赖和配置一些属性来快速集成Pulsar到他们的Spring Boot应用程序中。一旦集成完成,开发人员可以使用注解来定义消息的生产者和消费者。通过生产者注解,开发人员可以将消息发送到Pulsar集群,并指定消息的主题和内容。通过消费者注解,开发人员可以订阅Pulsar主题,并定义接收和处理消息的方法。 除了基本的生产者和消费者功能,pulsar-java-spring-boot-starter还提供了一些其他特性。例如,它支持失败重试机制,当消息发送或接收出现问题时,可以自动重试。它还支持消息过滤器,可以按条件过滤接收的消息。而且,它还提供了一些监控和管理功能,可以方便地监控消息的生产和消费情况。 总之,pulsar-java-spring-boot-starter为Spring Boot开发人员提供了一种方便、快捷地集成Apache Pulsar消息队列的方法。它简化了与Pulsar集群的交互,提供了易于使用的注解和工具类,让开发人员可以更专注于业务逻辑的实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值