spring原理

功能架构

在这里插入图片描述spring采用的是分层架构
基础模块为Core Container,这个是spring的基石,其它模块都是在此基础上扩展而来。

1. Test模块

  • 支持使用JUnit框架测试

2. Core Container模块

  • Beans:提供BeanFactory接口,提供访问Bean容器方法
  • Core:框架的基本组成部分,包括IoC、DI
  • Context:应用程序上下文,ApplicationContext接口提供配置信息
  • SpEL:Spring表达式语言,是一种强大的表达式语言,支持在运行时查询和操作对象图

3. AOP、Aspects、Instrumentation、Messaging

  • AOP:面向切面编程,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。实现方式:jdk、cglib
  • Aspects:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架
  • Instrumentation:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用
  • Messaging:消息传递,比如STOMP Messaging

4. Web模块

  • 支持WebSocket、Servlet

5. Data Access模块

  • Transactions:支持编程和声明式事务管理
  • JMS:支持集成Java消息服务,功能为信息的生产和消费
  • OXM:支持对象和XML映射,如 JAXB、Castor、XMLBeans、JiBX 和 XStream
  • JDBC:支持集成JDBC,大幅度减少了在开发过程中对数据库操作的编码
  • ORM:支持集成ORM框架,比如JPA、Hibernate和MyBatis

启动流程

在这里插入图片描述

重点关注四个接口:

  1. BeanDefinitionReader
  2. BeanDefinition
  3. BeanFactoryPostProcessor
  4. BeanFactory

spring启动流程的核心代码是AbstractApplicationContext#refresh()方法(spring5.2.1)

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 设置启动时间,容器状态,和property sources等
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 创建beanFactory
		// 内部通过XmlBeanDefinitionReader,加载bean definition
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 准备beanFactory使用前的各种配置,比如上下文类加载器,后置处理器等
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 默认是空实现
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// 调用BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 注册BeanPostProcessor
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			// 初始化MessageSource,辅助i18n
			initMessageSource();

			// Initialize event multicaster for this context.
			// 初始化上下文事件广播器
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 默认空实现
			onRefresh();

			// Check for listener beans and register them.
			// 注册监听器
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 实例化所有的单例bean(非懒加载)
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			// 发送相应事件给监听器
			finishRefresh();
		}

		catch (BeansException ex) {
			...
		}

		finally {
			...
		}
	}
}

BeanFactory和FactoryBean

BeanFactory

  • spring容器,实现类有ClassPathXmlApplicationContextAnnotationConfigApplicationContext

FactoryBean

  • 在spring容器中有两种Bean,一种是普通的Bean,另一种是FactoryBean
  • 根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,在id前面加一个&符号来获取
  • 使用场景:在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息,比如:SqlSessionFactoryBean
public interface FactoryBean<T> {
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
	@Nullable
	T getObject() throws Exception;
	@Nullable
	Class<?> getObjectType();
	default boolean isSingleton() {
		return true;
	}
}

代码位置:AbstractBeanFactory#getObjectForBeanInstance()

/**
 * Get the object for the given bean instance, either the bean
 * instance itself or its created object in case of a FactoryBean.
 */
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;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
		}
		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;
	}

	// 从FactoryBean中获取getObject()返回的对象
	Object object = null;
	if (mbd != null) {
		mbd.isFactoryBean = true;
	}
	else {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// Return bean instance from factory.
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		// 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);
	}
	return object;
}

Bean生命周期

在这里插入图片描述

创建bean的代码位置
AbstractAutowireCapableBeanFactory#doCreateBean()(spring5.2.1)

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

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		// 实例化bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isTraceEnabled()) {
			logger.trace("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		// 填充属性,循环依赖也在这里解决
		populateBean(beanName, mbd, instanceWrapper);
		// 调用aware和beanPostProcessor
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName, "省略...");
				}
			}
		}
	}

	// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

调用aware的代码位置

  • AbstractAutowireCapableBeanFactory#invokeAwareMethods() setBeanName、setBeanFactory
  • ApplicationContextAwareProcessor#invokeAwareInterfaces() setApplicationContext

Bean创建循环依赖问题

构造函数的循环依赖无法解决

spring为了解决单例的循环依赖问题,使用了三级缓存

三级缓存在类DefaultSingletonBeanRegistry

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

一级缓存singletonObjects:可以直接使用的完整对象;
二级缓存earlySingletonObjects:完成实例化而未初始化的对象;
三级缓存singletonFactories:lambda表达式

场景:A依赖B,B依赖A

  1. 先实例化A,将A的半成品(其实是lambda函数ObjectFactory)放到三级缓存singletonFactories中
    AbstractAutowireCapableBeanFactory#doCreateBean()
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  2. 给半成品A填充属性B时,发现B还未实例化,就会先去实例化B
  3. 在实例化B后,也将B的半成品(lambda函数ObjectFactory)放到三级缓存
  4. 给半成品B填充属性A,这时候能够从三级缓存中拿到半成品A
    DefaultSingletonBeanRegistry#getSingleton()
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 先从一级缓存拿
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			// 一级缓存没有,则从二级缓存拿
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				// 二级缓存没有,则从三级缓存拿
				// 三级缓存拿到bean后,将bean放入到二级缓存, 并从三级缓存中删除,
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}
  1. 拿到半成品A的lambda函数ObjectFactory后,调用ObjectFactory.getObject()方法最终会调用getEarlyBeanReference()方法,getEarlyBeanReference这个方法主要逻辑是如果bean被AOP切面代理则返回的是proxy对象,如果未被代理则返回的是原bean实例。
  2. 此时B注入的是一个半成品A,不过随着B初始化完成后,A会继续进行后续的初始化操作,最终B会注入的是一个完整的A实例。
  3. 最后,将B、A实例添加到一级缓存
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);
	}
}

通过上述流程分析,发现二级缓存好像没什么用。
其实不然,代码singletonObject = singletonFactory.getObject()是从三级缓存中获取bean对象,如果获取的是代理对象,每次返回的代理对象实例不是同一个,不满足单例要求,加上二级缓存存放代理对象可以避免这个问题。

通过上下文获取单例Bean,是从一级缓存singletonObjects获取
Person person = (Person) applicationContext.getBean(“person”);

AOP

AOP(Aspect-Oriented-Programming,面向切面编程)

动态代理两种实现方式

  • JDK动态代理:原对象有接口
  • CGLIB动态代理:原对象没有接口

spring代理实际上是对JDK代理和CGLIB代理做了一层封装,类图如下:
在这里插入图片描述
创建代理对象代码位置:AbstractAutoProxyCreator#wrapIfNecessary()

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 创建代理对象
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}
  1. spring aop严格的来说使用的是动态代理,所以实际上spring代理和AspectJ的关系并不大
  2. spring aop封装了jdk和cglib的动态代理实现,同时引入了AspectJ的编程方式和注解。这样不仅可以使用标准的AOP编程规范来编写代码,还可以使用AspectJ方式

AOP相关概念
通知(Advice) 包含了需要用于多个应用对象的横切行为,通俗一点说就是定义了“什么时候”和“做什么”。
连接点(Join Point) 是程序执行过程中能够应用通知的所有点
切点(Poincut) 是定义了在“什么地方”进行切入,哪些连接点会得到通知。显然,切点一定是连接点
切面(Aspect) 是通知和切点的结合。通知和切点共同定义了切面的全部内容
引入(Introduction) 允许我们向现有的类中添加新方法或者属性。
织入(Weaving) 是把切面应用到目标对象并创建新的代理对象的过程,分为编译期织入、类加载期织入和运行期织入

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值