从源码角度了解Spring容器

Spring的相关内容,我将展形成三篇博文从源码层次上介绍,当你读完三篇之后,也许会映入脑子一个词“扩展性”。那么恭喜你,你已经从源码的角度对Spring有所了解。

  • 基本流程
  • 核心类
  • Spring的可扩展性
  • bean生命周期

一. Bean创建

bean加载大致经历一下几个流程

  • 获取beanName
  • 合并bean定义,对父类的定义进行合并和覆盖
  • 实例化,使用构造或者工厂方法创建bean实例
  • 属性填充,寻找并且注入依赖,依赖的bean会递归的调用geyBean方法获取
  • 初始化,调用自定义的初始化方法
  • 获取最终的bean,如果是FactoryBean需要调用getObject,如果需要类型转换则调用TypeConverter进行转换。

2.1 转换beanName

	/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
	
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {
		final String beanName = transformedBeanName(name);
		......
}

转换name有下面几种情况

  • bean name,可以直接获取到定义 BeanDefinition。
  • alias name,别名,需要转化。
  • factorybean name, 带 & 前缀,通过它获取 BeanDefinition 的时候需要去除 & 前缀。

2.2 合并RootBeanDefinition

在配置文件中读取的BeanDefinition是GenericBeanDefinition,他只记录了一些当先类声明的属性和构造参数。

public class GenericBeanDefinition extends AbstractBeanDefinition {
	private String parentName;
	......
}

如果不存在继承关系,GenericBeanDefinition存储的是完整的信息,可以直接转换成RootBeanDefinition。但是如果存在继承关系,GenericBeanDefinition存在的是增量信息。

2.3 bean创建

  实例化bean分为两部分,包括Spring自己的bean,例如(internalConfigurationAnnotationProcessor)这部分是通过调用Spring后置处理器先初始化,用户创建的bean,最终的实例化是通过doCreateBean实现的

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

		//实例化 有参数的构造和无参数构造(开辟内存空间)
		instanceWrapper = createBeanInstance(beanName, mbd, args);
		// 能对beanDefinition修改的后置处理器
		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

		// Initialize the bean instance.
		Object exposedObject = bean;
		//属性赋值 
		populateBean(beanName, mbd, instanceWrapper);
		//初始化 见下面
		exposedObject = initializeBean(beanName, exposedObject, mbd);
		//销毁-注册 
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
/**
	 * Initialize the given bean instance, applying factory callbacks
	 * as well as init methods and bean post processors.
	 */
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	//Aware扩展点		
	invokeAwareMethods(beanName, bean);
	//BeanPostProcessor前置处理器
     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
     //若配置自定义的 init-method方法,则执行
     invokeInitMethods(beanName, wrappedBean, mbd);
    //BeanPostProcessor后置处理器
    applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	return wrappedBean;
}

2.4 解决循环依赖(三级缓存)

  Java创建bean有两种方式,一种通过有参数构造函数,第二种通过无参构造函数结合setter方法。Spring解决循环依赖是给予第二种,当遇到有参构造方法存在循环注入时,会直接抛出BeanCurrentlyInCreationException。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	//用于存放已经初始化好的bean bean name --> bean instance
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

    //提前曝光单例对象,存放原始bean(没有填充属性)用于解决循环依赖 bean name --> ObjectFactory
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

	//存放bean工厂对象 bean name --> bean instance
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
	
		/** Names of beans that are currently in creation */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
			
	private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
	
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject =this.singletonObjects.get(beanName);//一级缓存
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)){
	//正在创建的bean
	synchronized (this.singletonObjects) {
		singletonObject =this.earlySingletonObjects.get(beanName);//从二级缓存
		if (singletonObject == null && allowEarlyReference) {//允许提前曝光
	    singletonFactory=this.singletonFactories.get(beanName); 
	     //三级缓存
		if (singletonFactory != null) {
		singletonObject = singletonFactory.getObject();
		this.earlySingletonObjects.put(beanName,singletonObject);//放到二级缓存						
		this.singletonFactories.remove(beanName);//移除三级缓存
					}
				}
			}
		}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}


二. 核心类介绍

2.1 DefaultListableBeanFactory

  Spring容器,从根源上是beanFactory,但是真正可以作为独立的容器还是DefaultListableBeanFactory。因此DefaultListableBeanFactory才是Spring的鼻祖。个人认为DefaultListableBeanFactory拥有两种能力(1:BeanFactory, 2:DefinitionRegister)

在这里插入图片描述

接下来我们来逐层看每一个接口

1. BeanFactory,生成bean的工厂

public interface BeanFactory {
	/**
	 *  区分FactoryBean的实例,还是用factoryBean创建的Bean 
	 */
	String FACTORY_BEAN_PREFIX = "&";
	/**
	 * 获取对象实例
	 */
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	/**
	 * 工厂中是否包含name名称的bean
	 */
	boolean containsBean(String name);

	/**
	 * name的对象是否是单例
	 */
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	/**
	 * name对象是否是prototype
	 */
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	/**
	 * name的实例是否和制定类型一致
	 */
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	/**
	 * 对象工厂中name的实例
	 */
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	/**
	 * 判断对象工厂中名称name的别名
	 */
	String[] getAliases(String name);
}

2. BeanDefinitionRegistry:BeanDefinition注册信息

可以把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);
}

为了更清晰地说明DefaultListableBeanFactory的作用,列举一下DefaultListableBeanFactory中存储的一些重要对象及对象中的内容(网上查找)
image_1eroh01c11ncakg414la1ng9j54m.png-694kB

2.2 FactoryBean和BeanFactory

  BeanFactory是Spring中比较原始的bean,它负责。生产和管理bean。BeanFactory是IOC容器的核心接口,Spring给出多种实现类,eg(DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext)。BeanFactory和ApplicationContext是Spring框架两个IOC容器,ApplicationContext拥有BeanFactory的全部功能,此外还提供时间传播、资源访问等功能,因此推荐使用ApplicationContext。

  FactoryBean是一个接口,当IOC容器实现FactoryBean后,通过getBean(String beanName)获取的bean对象不是FactoryBean对象,而是实现这个类中的getObject()方法返回的对象,要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。 一般情况下spring通过反射机制利用bean的class属性指定实现类来实例化bean,按照传统的方法,需要在标签中配置大量的bean的信息,因此灵活性受限制。此时Spring提供来一个FactoryBean的工厂接口,用户可以通过实现接口定制化的实例化bean的逻辑。所以Spring提供了接近70多个FactoryBean的实现方法,隐藏了实例化一些复杂的bean的细节
FactoryBean源码

public interface FactoryBean<T> {  
    T getObject() throws Exception;  
    Class<?> getObjectType();  
    boolean isSingleton();  
}

FactoryBean实现类

//package  A
@Component
public class UserFactoryBean implements FactoryBean<UserService> {
    @Override
    public UserService getObject() throws Exception {
        return new UserService();
    }
    @Override
    public Class<?> getObjectType() {
        return UserService.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}
//package B 而且不需要Spring管理的对象
public class UserService {
    public UserService(){
        System.out.println("UserService construct");
    }
}
@Configurable
@ComponentScan("A")//只扫描A包
public class Appconfig {}

 public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        //com.jd.ads.union.demo.web.controller.service.UserService@543e710e
        System.out.println(context.getBean(UserService.class));
        //com.jd.ads.union.demo.web.controller.service.UserService@543e710e
        System.out.println(context.getBean("userFactoryBean"));
        //com.jd.ads.union.demo.web.controller.factory.UserFactoryBean@57f23557
        System.out.println(context.getBean("&userFactoryBean"));
    }
}

  注意: 按照之前的思路,userService并没有扫描注入到Spring中,但是getBean(UserService.class)是有对象的,而且和getBean(“userFactoryBean”)是同一个对象。下面看一下是如何让实现的.
容器启动:

@Override
public void preInstantiateSingletons(){
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) {//factoryBean
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//&
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						.......
					}
				}
		}
		else {getBean(beanName);}
		........
    }
}

getBean() -> doGetBean() -> getObjectForBeanInstance() -> getObjectFromFactoryBean() -> doGetObjectFromFactoryBean
image_1ere08ats6nl1j55mluafh145l.png-718.3kB

通过FactoryBean.Bean()来回调方法,返回UserService对象

2.3 解析 @Configuration

  ConfigurationClassPostProcessor 是BeanDefinitionRegistryPostProcessor的后置处理器,下面将详细介绍如何解析@Configuration( Build and validate a configuration model based on the registry of Configuration classes)。

image_1erqn1jjt1ikqc741m13vjt1gpc9.png-1141.4kB

  checkConfigurationClassCandidate()作用:Check whether the given bean definition is a candidate for a configuration class

	/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 */
	@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {
     // @PropertySource
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable){
		sourceClass.getMetadata(), PropertySources.class,
		org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
			else {}
		}

		//@ComponentScan
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
		sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
	}

	// @Import
	processImports(configClass, sourceClass, getImports(sourceClass), true);

	//@ImportResource
	AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
	if (importResource != null) {
	String[] resources = importResource.getStringArray("locations");
	Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
	for (String resource : resources) {
	    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
		configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// @Bean 可能会对bean做增强
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

  所以@PropertySource,@ComponentScan,@Import,@ImportResource,@Bean,父类和子类,其中只有@ComponentScan这一块遇到@Component注解才会注册bean


三.Spring的扩展点

3.1 ImportBeanDefinitionRegistrar

  ImportBeanDefinitionRegistrar需要配合@Import注解,@Configuration,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类,实现动态注册bean。

/**
 * Interface to be implemented by types that register additional bean definitions when
 * processing Configuration classes. Useful when operating at the bean definition @Configuration and link ImportSelector, classes of this type
 * may be provided to the @Import annotation 
 **/
 @Component
public class UserImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //将user的 definition 注册到容器中
        System.out.println("ImportBeanDefinitionRegistrar(),begin");
        GenericBeanDefinition definition = new GenericBeanDefinition();
        definition.setBeanClass(User.class);
        definition.getPropertyValues().add("name","beanName2");
        definition.getPropertyValues().add("age","202");
        registry.registerBeanDefinition("user2",definition);
        System.out.println("ImportBeanDefinitionRegistrar(),end");
    }
}

@Configurable
@EnableAspectJAutoProxy
@Import(UserImportBeanDefinitionRegistrar.class)
public class Appconfig {
}
 public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        User user2 = context.getBean("user2",User.class);
        System.out.println("user2="+user2);
        System.out.println("userName2="+user2.getName());
}

ImportBeanDefinitionRegistrar(),begin
ImportBeanDefinitionRegistrar(),end
user2=com.jd.ads.union.demo.web.controller.bean.factory.User@4b168fa9
userName2=beanName2

3.2 BeanDefinitionRegistryPostProcessor

  BeanDefinitionRegistryPostProcessor的作用:动态注册bean

/**
 * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
 * the registration of further bean definitions <i>before</i> regular
 * BeanFactoryPostProcessor detection kicks in. In particular,
 * BeanDefinitionRegistryPostProcessor may register further bean definitions
 * which in turn define BeanFactoryPostProcessor instances.
BeanFactoryPostProcessor检测开始之前注册更多的bean定义,在BeanFactoryPostProcessor之前的一层扩展

举例 手动汪容器中注册一个BeanDefinition

public class User {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

UserBeanDefinitionRegistryPostProcessor

@Component
public class UserBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //将user的 definition 注册到容器中
        System.out.println("postProcessBeanDefinitionRegistry(),begin");
        GenericBeanDefinition definition = new GenericBeanDefinition();
        definition.setBeanClass(User.class);
        definition.getPropertyValues().add("name","beanName");
        definition.getPropertyValues().add("age","20");
        registry.registerBeanDefinition("user",definition);
        System.out.println("postProcessBeanDefinitionRegistry(),end");
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("postProcessBeanFactory()");
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        User user = context.getBean(User.class);
        System.out.println("user="+user);
    }

refresh() -> invokeBeanFactoryPostProcessors() ->invokeBeanFactoryPostProcessors()
image_1ero52abhj3s1mah1oi616et1i9lm.png-918kB
  从执行的源码可以看出,BeanDefinitionRegistryPostProcessor,是有先执行于BeanFactoryPostProcessor。 BeanDefinitionRegistryPostProcessor,在mybatis用的比较多,因为一般情况下mapper是一个interface,因此在扫描完成之后会将mapper的definition信息加载容易中,用代理代替接口,放在容器中。后续再mybatis讲解。

3.2 BeanFactoryPostProcessor

ImportBeandefinitionRegistratr(),begin
ImportBeandefinitionRegistratr(),end
PostProcessBeandefinitionRegistratr(),begin
PostProcessBeandefinitionRegistratr(),end
user = User@4654646
userName = beanName
user2 = User@46544645
userName2 = beanName2
注意三个扩展点的前后执行准许

3.4 BeanPostProcessor

在实例化之后

3.5 Aware接口

  Aware相关的接口目的我认为不是扩展,而是注入相关的依赖, 通过让Bean实现Aware接口,则可以在bean中获得相应Spring容器资源。
Spring中提供的Aware接口有:

  • BeanNameAware:注入当前 bean 对应 beanName;
  • BeanClassLoaderAware:注入加载当前 bean 的 ClassLoader;
  • BeanFactoryAware:注入 当前BeanFactory容器 的引用
private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

  以上是针对BeanFactory类型的容器,而对于ApplicationContext类型的容器,也提供来Aware相关的接口

  • EnvironmentAware:注入 Enviroment,一般用于获取配置属性;
  • EmbeddedValueResolverAware:注入 EmbeddedValueResolver(Spring
    EL解析器),一般用于参数解析;
  • ApplicationContextAware(ResourceLoader、ApplicationEventPublisherAware、MessageSourceAware):注入ApplicationContext 容器本身。
// ApplicationContextAwareProcessor.java
private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
 ........
}

  以上也仅仅列举了几个Spring的扩展点,Spring其实从最开始的扫描扫最后的销毁,每一个都扩展点,正式这种强大的扩展性,才铸就了今天这么多人的使用。


参考文章:

Bean加载流程概览
如何记忆Spring Bean的生命周期
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值