Spring中Bean注入源码示例解析

目录
  • BeanDefinition和Bean
  • BeanDefinition的注入
    • BeanDefinitionRegistry接口
    • BeanDefinitionRegistry的实现类
    • SimpleBeanDefinitionRegistry
    • DefaultListableBeanFactory
  • Bean的注入
    • SingletonBeanRegistry接口
    • SingletonBeanRegistry的实现类
    • AbstractBeanFactory
    • DefaultSingletonBeanRegistry
  • 总结

BeanDefinition和Bean

在Spring中Bean的注入涉及两部分:

  • BeanDefinition
  • Bean

两个对象存在先后顺序,先注入BeanDefinition之后才执行Bean对象的注入。

那么两者有什么关联呢?

BeanDefinition和Bean的关系:可以理解为BeanDefinition是Bean的包装类,类似Java中类和属性的关系。

BeanDefinition是对Bean对象的包装,BeanDefinition中封装了Bean相关的描述,比如bean对象,bean的单例还是原型、bean的父级、懒加载方式等等。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	void setScope(@Nullable String scope);
	@Nullable
	String getScope();
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();
}
//bean的原数据
public interface BeanMetadataElement {
	@Nullable
	Object getSource();
}

在BeanDefinition中继承了BeanMetadataElement,该类是Bean的原数据,该类中实例化了Bean对象为Object。因此在BeanDefinition中调用getSource就可以获取到Bean对象。

分清楚BeanDefinition和Bean之后再看BeanDefinition的注入,因为只有注入了BeanDefinition才会注入后续的Bean。

BeanDefinition的注入

BeanDefinitionRegistry接口

BeanDefinitin的注入通过接口BeanDefinitionRegistry抽象了各种对BeanDefinition的操作,例如

  • BeanDefinitionRegistry#registerBeanDefinition(注入到beanDefinition中)
  • BeanDefinitionRegistry#removeBeanDefinition(从beanDefinition容器中移除)
  • BeanDefinitionRegistry#getBeanDefinition(获取BeanDefinition)
public interface BeanDefinitionRegistry extends AliasRegistry {
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	boolean containsBeanDefinition(String beanName);
	String[] getBeanDefinitionNames();
	int getBeanDefinitionCount();
	boolean isBeanNameInUse(String beanName);
}

该接口是操作BeanDefinition的基础接口,该类是一个接口类型并不是一个抽象类,因此该接口中不会定义任何BeanDefinition的容器,BeanDefinition的容器只在各实现类中定义并使用。任何需要操作BeanDefinition的实现都需要实现该接口。

BeanDefinitionRegistry的实现类

找到操作BeanDefinition的接口就可以通过接口查看接口的实现类,进而找到BeanDefinition的应用。

BeanDefinition常见的几个实现类有:

  • DefaultListableBeanFactory
  • SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistry

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
	/**beanDefinition的容器,通过ConcurrentHashMap实现. */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
	//该类的实现方法只是实现了最简单的beanDefinition的注入,在Java开发环境中并不会使用该实现类
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		Assert.hasText(beanName, "'beanName' must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
}

该实现类中只做了最简单的注入功能,没有任何的逻辑处理,因此在实际开发过程中Spring并不会使用该类。

DefaultListableBeanFactory

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
		//beanDefinition的容器
		private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
		//向BeanFactory中注入BeanDefinition
		public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
			Assert.hasText(beanName, "Bean name must not be empty");
			Assert.notNull(beanDefinition, "BeanDefinition must not be null");
			if (beanDefinition instanceof AbstractBeanDefinition) {
				try {
					((AbstractBeanDefinition) beanDefinition).validate();
				}
				catch (BeanDefinitionValidationException ex) {
					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
							"Validation of bean definition failed", ex);
				}
			}
			BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
			//判断beanDefinition容器中是否已存在该beanDefinition
			if (existingDefinition != null) {
				//是否可以覆盖
				if (!isAllowBeanDefinitionOverriding()) {
					throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
				} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
					// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
					if (logger.isInfoEnabled()) {
						logger.info("Overriding user-defined bean definition for bean '" + beanName +
								"' with a framework-generated bean definition: replacing [" +
								existingDefinition + "] with [" + beanDefinition + "]");
					}
				} else if (!beanDefinition.equals(existingDefinition)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Overriding bean definition for bean '" + beanName +
								"' with a different definition: replacing [" + existingDefinition +
								"] with [" + beanDefinition + "]");
					}
				} else {
					if (logger.isTraceEnabled()) {
						logger.trace("Overriding bean definition for bean '" + beanName +
								"' with an equivalent definition: replacing [" + existingDefinition +
								"] with [" + beanDefinition + "]");
					}
				}
				//覆盖beanDefinition
				this.beanDefinitionMap.put(beanName, beanDefinition);
			} else { //容器中不存在该beanDefinition的处理
				if (hasBeanCreationStarted()) {
					synchronized (this.beanDefinitionMap) { //对beanDefinition加锁
						//注入该beanDefinition
						this.beanDefinitionMap.put(beanName, beanDefinition);
						List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
						updatedDefinitions.addAll(this.beanDefinitionNames);
						updatedDefinitions.add(beanName);
						this.beanDefinitionNames = updatedDefinitions;
						if (this.manualSingletonNames.contains(beanName)) {
							Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
							updatedSingletons.remove(beanName);
							this.manualSingletonNames = updatedSingletons;
						}
					}
				}
				else {
					// Still in startup registration phase
					this.beanDefinitionMap.put(beanName, beanDefinition);
					this.beanDefinitionNames.add(beanName);
					this.manualSingletonNames.remove(beanName);
				}
				this.frozenBeanDefinitionNames = null;
			}
		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
}

DefaultListableBeanFactory是默认使用的注入BeanDefinition的实现类,可以看到该实现类中对注入BeanDefinition做了很多的逻辑判断,日常开发启动容器过程中都会使用该实现类注入BeanDefinition进行后续的Bean注入。

Bean的注入

BeanDefinition注入后后续执行Bean的注入,bean注入的方式也是将bean注入到bean的容器中,因此在Spring中BeanDefinition和Bean都是通过容器化的方式操作的,那么在Bean的注入中也通过对应的接口定义对Bean的操作,该接口就是SingletonBeanRegistry

SingletonBeanRegistry接口

该接口实现了对Bean的操作:

  • SingletonBeanRegistry#registerSingleton(将bean注入到容器中)
  • SingletonBeanRegistry#getSingleton(从容器中获取bean)
public interface SingletonBeanRegistry {
	//注入bean
	void registerSingleton(String beanName, Object singletonObject);
	//获取bean
	@Nullable
	Object getSingleton(String beanName);
	//是否存在bean
	boolean containsSingleton(String beanName);
	String[] getSingletonNames();
	int getSingletonCount();
	Object getSingletonMutex();
}

SingletonBeanRegistry的实现类

SingletonBeanRegistry的实现类有多个,分别为:

  • AbstractBeanFactory
  • DefaultListableBeanFactory
  • DefaultSingletonBeanRegistry
  • FactoryBeanRegistrySupport
  • AbstractAutowireCapableBeanFactory

下面说两个有代表性的:AbstractBeanFactory和DefaultSingletonBeanRegistry

AbstractBeanFactory

该实现类是一个抽象类,即该类是bean的工厂类,其中主要实现的是可以复用的具体逻辑,该抽象类中包含获取bean、beanPostProcessor、初始化bean、销毁bean等对bean的操作抽象类。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	//获取bean的方式平时使用ApplicationContext就是最终调用该方法
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}
	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}
	public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
			throws BeansException {
		return doGetBean(name, requiredType, args, false);
	}
	/**
	* 从容器中获取bean的主要逻辑
	*/
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		final String beanName = transformedBeanName(name);
		Object bean;
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
			//省略部分代码
			try {
				//先获取beanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}
				// 单例模式下获取bean的方式
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						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()) {//原型模式下的bean的获取
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						//原型模式每次都需要创建bean
						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, () -> {
							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;
			}
		}
		//省略部分代码
		return (T) bean;
	}
	//将实现beanPostProcessor的实现类加入到链表中用于对bean的前置或者后置处理
	@Override
	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		// Remove from old position, if any
		this.beanPostProcessors.remove(beanPostProcessor);
		// Track whether it is instantiation/destruction aware
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
		// Add to end of list
		this.beanPostProcessors.add(beanPostProcessor);
	}
	//销毁bean的方法
	@Override
	public void destroyBean(String beanName, Object beanInstance) {
		destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
	}
	protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
		new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
	}
}

DefaultSingletonBeanRegistry

该实现类通过名字也可以推断出该实现类是对单例bean的注入,该类中实现了bean的所有容器,平时开发过程中Spring容器启动就是使用了该实现类中的容器,该实现类是对bean最终注入的实现,涉及的四个容器主要有:

  • singletonObjects
  • singletonFactories
  • earlySingletonObjects
  • registeredSingletons

四个容器其中三个的核心作用是解决循环依赖,这里不展开说。

找一条主线梳理下Bean注入的过程,当BeanDefinition注入成功后,后续执行bean的注入,以AbstractAutowireCapableBeanFactory的实现为例,该实现类中会对bean的注入,整个注入的链路如下:

  • 获取资源数据:CommonAnnotationBeanPostProcessor#autowireResource
  • 通过beanName解析bean:AbstractAutowireCapableBeanFactory#resolveBeanByName
  • 调用抽象类中获取bean:AbstractBeanFactory#getBean
  • 执行抽象类中获取bean的核心逻辑:AbstractBeanFactory#doGetBean
  • bean不存在时创建bean:AbstractAutowireCapableBeanFactory#createBean
  • 获取单例bean:efaultSingletonBeanRegistry#getSingleton
  • 单例bean不存在将类注入到容器中:DefaultSingletonBeanRegistry#addSingleton
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	//单例bean的容器,开发过程中获取的bean都是从该容器中获取的:即所谓的一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	//单例bean的beanFactory的容器:即所谓的三级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	//提前初始化的bean的容器,该容器的bean并没有任何属性值只是提前将bean注入到该容器中用于后续的判断
	//即所谓的二级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
	//已注册的单例bean的beanName列表
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
	//注入bean的方法
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
												"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
			addSingleton(beanName, singletonObject);
		}
	}
	/**
	* 将bean注入容器中,操作四个容器主要用于bean的循环依赖问题
	*/
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
}

总结

以上就是对bean注入从源码的梳理,该梳理主要从bean注入前的准备(beanDefinition的注入)和bean注入的实现来完成,从整个梳理中学到最多的主要有两点:

  • 抽象的思想:在BeanDefinition的实现和Bean的实现逻辑中,都完成高度抽象并且遵循单一原则和高度抽象,代码的可扩展性和复用性很高,我们作为开发者也可以通过Spring暴露的各种Registry接口实现对Bean的操作。
  • 容器化思想:从BeanDefinition和Bean的注入来看,整个的实现思路都是基于容器化思想来实现的,将开发中需要关心的对象都实例化到容器中,开发者在使用时只要从容器中获取即可,并且获取bean的方式也很灵活,开发者在使用和扩展性上更便利。

对于源码的学习自己理解来说并不是背其中的代码,而是学习大佬实现代码的思想,为什么可以抽象出扩展性这么高的代码,并且从源头梳理下来都能很轻松的按照主线一步一步梳理到目的地,这也是每个开发者需要学习的地方,提高自己代码的可读性和可扩展性,能够掌握面向对象的核心:封装、继承、多态

以上就是Spring中Bean注入源码示例解析的详细内容,更多关于Spring Bean注入的资料请关注我们其它相关文章!

(0)

相关推荐

  • Spring单元测试控制Bean注入的方式

    目录 通过xml文件进行注入 通过xml加注解方式进行注入 通过注解进行注入 @Component和@Configuration的区别 使用FactoryBean 通过@Import导入 手动注入(registerBean) 通过ImportSelector进行注入 通过ImportBeanDefinitionRegistrar进行注入 通过BeanDefinitionRegistryPostProcessor进行注入 通过xml文件进行注入 在配置文件中指定要注入的bean <?xml ver

  • Spring中bean集合注入的方法详解

    目录 Map注入 List注入 Set注入 数组注入 应用 哈喽大家好啊,我是Hydra. Spring作为项目中不可缺少的底层框架,提供的最基础的功能就是bean的管理了.bean的注入相信大家都比较熟悉了,但是有几种不太常用到的集合注入方式,可能有的同学会不太了解,今天我们就通过实例看看它的使用. 首先,声明一个接口: public interface UserDao { String getName(); } 然后定义两个类来分别实现这个接口,并通过@Component注解把bean放入s

  • Spring Bean注册与注入实现方法详解

    目录 1. 逻辑上的 Bean 注册 2. XML 注册 Bean 到自建的库中 2.1 工厂方法 2.2 使用工厂方法和实例化工厂注册 Bean 3. XML 配合注解进行 Bean 注册 4. 使用注解注册 Bean 4.1 注解方式注册的必要条件 4.2 用到的注解 4.3 @Component注解注入 4.4 使用 @Bean 注解注册 5. 通过注解注入 Bean 6. 注入时的一个坑点 7. 获取 库中的对象 上接[Spring]spring核心思想——IOC和DI 上篇文章结尾简单

  • Spring容器注入bean的五种方法逐个解析

    目录 前言 @ComponentScan+@Component @Configuration+@Bean 通过@Import注解 1.直接导入类的class 2.导入配置类 3.导入ImportSelector的实现类 4.导入ImportBeanDefinitionRegistrar的实现类 借助FactoryBean接口 借助BeanDefinitionRegistryPostProcessor接口 前言   我们在项目开发中都用到Spring,知道对象是交由Spring去管理.那么将一个对

  • 详解Spring Bean的集合注入和自动装配

    目录 一.Spring Bean 集合注入 集合常用标签 案例 二.Spring Bean自动装配 什么是自动装配 自动装配的方式 案例 注意点 一.Spring Bean 集合注入 在[Spring学习笔记(三)]已经讲了怎么注入基本数据类型和引用数据类型,接下来介绍如何注入比较特殊的数据类型——集合 集合常用标签 集合注入,用法也很简单,只需要在 Bean 标签下的 <property> 或<constructor-arg>元素中添加以下集合的标签,再通过value或者ref进

  • 一文详解Spring如何控制Bean注入的顺序

    目录 简介 构造方法依赖(推荐) @DependsOn(不推荐) BeanPostProcessor(不推荐) 简介 说明 本文介绍Spring如何控制Bean注入的顺序. 首先需要说明的是:在Bean上加@Order(xxx)是无法控制bean注入的顺序的! 控制bean的加载顺序的方法 1.构造方法依赖 2.@DependsOn 注解 3.BeanPostProcessor 扩展 Bean初始化顺序与类加载顺序基本一致:静态变量/语句块=> 实例变量或初始化语句块=> 构造方法=>

  • Spring依赖注入与第三方Bean管理基础详解

    目录 1. 注解开发依赖注入 1.1 使用@Autowired注解开启自动装配模式 1.2 使用@Qualifier注解指定要装配的bean名称 1.3 使用@Value实现简单类型注入 2. 注解开发管理第三方Bean 2.1 单独定义配置类 2.2 将独立的配置类加入核心配置 3.注解开发为第三方Bean注入资源 3.1 简单类型依赖注入 3.1.1 新建jdbc.properties文件 3.1.2 在配置类或者配置文件中加载属性文件. 3.1.3 使用EL表达式读取properties属

  • Spring Bean属性注入的两种方式详解

    目录 属性注入概念 一.构造器注入 示例1 注意点 二.setter注入 示例2 三.如何选择注入方式 属性注入概念 Spring 属性注入(DI依赖注入)有两种方式:setter注入,构造器注入. 这个注入的属性可以是普通属性(基本数据类型与String等),也可以是一个引用数据类型(主要是对象),或者是一个集合(list.map.set等) 下表是属性注入bean标签中常用的元素 元素名称 描述 constructor-arg 构造器注入.该元素的 index 属性指定构造参数的索引(从 0

  • spring获取bean的源码解析

    介绍 前面一章说了AbstractApplicationContext中的refresh方法中的invokeBeanFactoryPostProcessors.主要是调用BeanFactoryPostProcessor.其中也有获取bean的过程,就是beanFactory.getBean的方法.这一章就说下getBean这个方法.由于spring中获取bean的方法比较复杂,涉及到的流程也非常多,这一章就先说下整个大体的流程.其中的细节会在后面也会慢慢说. 源码 直接看源码吧 @Overrid

  • Spring启动流程refresh()源码深入解析

    一.Spring容器的refresh() spring  version:4.3.12  ,尚硅谷Spring注解驱动开发-源码部分 //refresh():543, AbstractApplicationContext (org.springframework.context.support) public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdo

  • Java Spring @Lazy延迟注入源码案例详解

    前言 有时候我们会在属性注入的时候添加@Lazy注解实现延迟注入,今天咱们通过阅读源码来分析下原因 一.一个简单的小例子 代码如下: @Service public class NormalService1 { @Autowired @Lazy private MyService myService; public void doSomething() { myService.getName(); } } 作用是为了进行延迟加载,在NormalService1进行属性注入的时候,如果MyServ

  • lazy init控制加载在Spring中如何实现源码分析

    目录 一.lazy-init说明 二.lazy-init 属性被设置的地方 三.lazy-init发挥作用的地方 四.问答 一.lazy-init说明 ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化(也就是依赖注入). 提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的singleton bean. 通常情况下这是件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小

  • Flink 侧流输出源码示例解析

    目录 Flink 侧流输出源码解析 源码解析 TimestampedCollector#collect CountingOutput#collect BroadcastingOutputCollector#collect RecordWriterOutput#collect ProcessOperator#ContextImpl#output CountingOutput#collect BroadcastingOutputCollector#collect RecordWriterOutput

  • JS前端操作 Cookie源码示例解析

    目录 引言 源码分析 使用 源码 分析 set get remove withAttributes & withConverter 总结 引言 前端操作Cookie的场景其实并不多见,Cookie也因为各种问题被逐渐淘汰,但是我们不用Cookie也可以学习一下它的思想,或者通过这次的源码来学习其他的一些知识. 今天带来的是:js-cookie 源码分析 使用 根据README,我们可以看到js-cookie的使用方式: // 设置 Cookies.set('name', 'value'); //

  • MyBatis SqlSource源码示例解析

    目录 正文 SqlNode SqlNode接口定义 BoundSql SqlSource SqlSource解析时机 SqlSource调用时机 总结 正文 MyBatis版本:3.5.12. 本篇讲从mybatis的角度分析SqlSource.在xml中sql可能是带?的预处理语句,也可能是带$或者动态标签的动态语句,也可能是这两者的混合语句. SqlSource设计的目标就是封装xml的crud节点,使得mybatis运行过程中可以直接通过SqlSource获取xml节点中解析后的SQL.

  • Flutter加载图片流程之ImageProvider源码示例解析

    目录 加载网络图片 ImageProvider resolve obtainKey resolveStreamForKey loadBuffer load(被废弃) evict 总结 困惑解答 加载网络图片 Image.network()是Flutter提供的一种从网络上加载图片的方法,它可以从指定的URL加载图片,并在加载完成后将其显示在应用程序中.本节内容,我们从源码出发,探讨下图片的加载流程. ImageProvider ImageProvider是Flutter中一个抽象类,它定义了一种

  • OpenMP task construct 实现原理及源码示例解析

    目录 前言 从编译器角度看 task construct Task Construct 源码分析 总结 前言 在本篇文章当中主要给大家介绍在 OpenMP 当中 task 的实现原理,以及他调用的相关的库函数的具体实现. 在本篇文章当中最重要的就是理解整个 OpenMP 的运行机制. 从编译器角度看 task construct 在本小节当中主要给大家分析一下编译器将 openmp 的 task construct 编译成什么样子,下面是一个 OpenMP 的 task 程序例子: #inclu

  • Python 装饰器常用的创建方式及源码示例解析

    目录 装饰器简介 基础通用装饰器 源码示例 执行结果 带参数装饰器 源码示例 源码结果 源码解析 多装饰器执行顺序 源码示例 执行结果 解析 类装饰器 源码示例 执行结果 解析 装饰器简介 装饰器(decorator)是一种高级Python语法.可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用.修饰器经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理

随机推荐