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中存储的一些重要对象及对象中的内容(网上查找)
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
通过FactoryBean.Bean()来回调方法,返回UserService对象
2.3 解析 @Configuration
ConfigurationClassPostProcessor 是BeanDefinitionRegistryPostProcessor的后置处理器,下面将详细介绍如何解析@Configuration( Build and validate a configuration model based on the registry of Configuration classes)。
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()
从执行的源码可以看出,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其实从最开始的扫描扫最后的销毁,每一个都扩展点,正式这种强大的扩展性,才铸就了今天这么多人的使用。