Spring IoC源码分析

这是一篇纯源码的文章,可能有些枯燥,希望大家喜欢。不废话

Spring IoC源码分析_第1张图片


一、源码编译

1.下载:

git clone https://github.com/spring-projects/spring-framework.git 1

cd spring-framework/

2.编译:

先配置gradle编译环境

gradle -v

idea中配置gradle

Spring IoC源码分析_第2张图片

3.直接导入idea,在Terminal中执行如下命令,编译Spring源码

gradlew spring-oxm:compileTestJava

4.正常情况是不会确实cglib包的,如果确实,在Terminal中执行

gradle objenesisRepackJar gradle cglibRepackJar

会在Spring-framework\spring-core\build\libs生成缺失的jar

二、IoC容器设计理念

IoC也称为依赖注入dependency injection, DI)。它是一个对象定义依赖关系的过程,也就是 说,对象只通过构造函数参数、工厂方法的参数或对象实例构造或从工厂方法返回后在对象实 例上设置的属性来定义它们所使用的其他对象。然后容器在创建bean时注入这些依赖项。这 个过程基本上是bean的逆过程,因此称为控制反转(IoC)

在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和管理的对象。

IoC容器设计理念:通过容器统一对象的构建方式,并且自动维护对象的依赖关系。

三、Spring IoC的使用及其原理分析

1.bean的装配方式 xml

ApplicationContext context = new

ClassPathXmlApplicationContext("spring.xml");

实现FactoryBean

public class MyFactroyBean implements FactoryBean {

@Override

public Object getObject() throws Exception {

return new ReentrantLock();

}

@Override

public Class getObjectType() {

return ReentrantLock.class;

}

}

思考:FactoryBean和BeanFactory的区别?

AbstractBeanFactory#getObjectForBeanInstance

!(beanInstance instanceof FactoryBean) ||

BeanFactoryUtils.isFactoryDereference(name)

ObjectFactory 和FactoryBean的区别?

@Component +@ComponentScan @Component , @Repository,@Service , @Controller @Component 是通用注解,其他三个注解是这个注解的拓展,并且具有了特定的功能 @Repository 注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持 久层异常的功能。 @Service 层是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。 @Controller 层是spring-mvc的注解,具有将请求进行转发,重定向的功能。

@ComponentScan("bat.ke.qq.com")

@Configuration

public class AppConfig {

}

AnnotationConfigApplicationContext context = new

AnnotationConfigApplicationContext(AppConfig.class)

思考: @Configuration和@Component区别?

@Configuration 实现了@Component,还有其他作用

@Bean+ @Configuration

@Configuration

public class AppConfig {

@Bean

public User user(){

return new User();

}

}

思考:配置 @Configuration和不配置的区别? 不配置@Configuration: 当内部method bean发生彼此依赖的时候会导致多例 @Configuration: 1.将@Configuration配置的Appconfig由普通类型转变为cglib代理类型 2.将AppConfig的beanDefinitioin属性赋值为full类型的(不配置的是lite) @Configuration源码分析: ConfigurationClassPostProcessor#postProcessBeanFactory

AbstractApplicationContext#invokeBeanFactoryPostProcessors

>PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(Configu

rableListableBeanFactory, BeanFactoryPostProcessor>)

>ConfigurationClassPostProcessor#postProcessBeanFactory

>> enhanceConfigurationClasses(beanFactory); //增强配置类 cglib

// 转换为cglib类型

>>Class enhancedClass = enhancer.enhance(configClass,

this.beanClassLoader);

@Import

@ComponentScan("bat.ke.qq.com")

@Configuration

@Import(value = MyImportBeanDefinitionRegistrar.class)

public class AppConfig {

@Bean

public User user(){

return new User();

}

}

@Import(AppConfig2.class)

ImportSelector

public class MyImportSelector implements ImportSelector {

@Override

public String[] selectImports(AnnotationMetadata

importingClassMetadata)

return new String[]{Fox.class.getName()};// 只能根据byType

}

}

ImportBeanDefinitionRegistrar

public class MyImportBeanDefinitionRegistrar implements

ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata

importingClassMetadata,BeanDefinitionRegistry registry) {

//创建BeanDefinition

RootBeanDefinition rootBeanDefinition = new

RootBeanDefinition(Fox.class);

// 注册到容器

registry.registerBeanDefinition("fox",rootBeanDefinition);

}

}

@ImportResource("spring.xml")

@Conditional

@ComponentScan("bat.ke.qq.com")

@Configuration

public class AppConfig {

@Bean

public Cat cat(){

return new Cat();

}

@Bean

@Conditional(value = MyConditional.class)

public Fox fox(){

return new Fox()

}

}

public class MyConditional implements Condition {

@Override

public boolean matches(ConditionContext context, AnnotatedTypeMetadata

metadata) {

if(context.getBeanFactory().containsBean("cat"))

return true;

return false;

}

}

2.bean的注册原理

思考:bean的属性是什么对象承载的? bean是如何注册到容器中的?

BeanDefinition (Bean定义) 承载bean的属性信息

BeanDefinitionRegistry(Bean注册器) bean的id作为key注册 beanName

AliasRegistry (别名注册器) bean的name作为key注册

BeanDefinitionHolder 包装 BeanDefinition id name(多个)

BeanDefinitionReader(Bean定义读取) 读取spring配置文件

BeanDefinitionParser bean定义解析器 parser解析 schema

ConfigurationClassParser 配置类解析器

BeanMethod @bean修饰的方法bean

ConfigurationClass 配置类 缓存BeanMethod到 beanMethods

Beanfactory (bean工厂) 生产bean

xml配置

//创建一个简单注册器

//BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();

//创建一个实现了注册器的工厂

BeanDefinitionRegistry registry = new DefaultListableBeanFactory();

//创建bean定义读取器

BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);

// 创建资源读取器

//DefaultResourceLoader resourceLoader = new DefaultResourceLoader();

// 获取资源

//Resource xmlResource = resourceLoader.getResource("spring.xml");

reader.loadBeanDefinitions("spring.xml");

// 装载Bean的定义

reader.loadBeanDefinitions(xmlResource);

// 打印构建的Bean 名称

System.out.println(Arrays.toString(register.getBeanDefinitionNames());

// 工厂调用getBean方法

System.out.println(regis解析xml并注册beanter.getBean("user"));

源码分析

AbstractApplicationContext#refresh

>>obtainFreshBeanFactory();

>>refreshBeanFactory();

>>loadBeanDefinitions(beanFactory);

>>loadBeanDefinitions(beanDefinitionReader);

>XmlBeanDefinitionReader#doLoadBeanDefinitions

>DefaultBeanDefinitionDocumentReaderarseBeanDefinitions

// 解析xml bean标签

>BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element)

// 生成beanName(id 和name) 和beanDefinition

>BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element,

BeanDefinition)

>DefaultBeanDefinitionDocumentReader#processBeanDefinition

>>BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,

getReaderContext().getRegistry());

>BeanDefinitionReaderUtils#registerBeanDefinition

>> registry.registerBeanDefinition(beanName,

definitionHolder.getBeanDefinition());

// 注册beanDefiniton

>DefaultListableBeanFactory#registerBeanDefinition

>>this.beanDefinitionMap.put(beanName, beanDefinition);

>>this.beanDefinitionNames.add(beanName);

>>this.manualSingletonNames.remove(beanName);

java Configuration

AnnotationConfigApplicationContext context =

new AnnotationConfigApplicationContext(AppConfig.class);

// 通过容器获取到beanFactory 即是工厂,又是注册器

DefaultListableBeanFactory factory =

context.getDefaultListableBeanFactory();

RootBeanDefinition beanDefinition = new RootBeanDefinition(Fox.class);

factory.registerBeanDefinition("fox",beanDefinition);

//beanDefinition.setAutowireMode(2);

//spring 填充属性

beanDefinition.getPropertyValues().add("name","foxxx");

ConfigurationClassPostProcessor#processConfigBeanDefinitions ConfigurationClassParser#processConfigurationClass ConfigurationClassParser#doProcessConfigurationClass

gApplicationContext context = new

AnnotationConfigApplicationContext(AppConfig.class);

eregister(annotatedClasses);

>AnnotatedBeanDefinitionReader#registerBean(Class)

// 注册appConfig 到容器

>AnnotatedBeanDefinitionReader#doRegisterBean

// 容器启动

tBean("fox"));

源码分析

AbstractApplicationContext#refresh

>>invokeBeanFactoryPostProcessors(beanFactory);

>PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcess

ors

>ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

>ConfigurationClassPostProcessor#processConfigBeanDefinitions

>>ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef,

this.metadataReaderFactory) // 设置配置类属性是full还是lite

>> parser.parse(candidates); // 解析配置类

>ConfigurationClassParser#parse(Set)

>ConfigurationClassParser#parse(AnnotationMetadata, String)

>> doProcessConfigurationClass(confi// 配置类解析器

gClass, sourceClass);

>ConfigurationClassParser#doProcessConfigurationCla 将@Component修饰的bean

注册到容器ss

// 解析@ComponentScan

>> this.componentScanParser.parse(componentScan,

sourceClass.getMetadata().getClassName());

>>>ComponentScanAnnotationParser#parse

// basePackages属性修饰的

>>> ClassPathBeanDefinitionScanner#doScan

// 找到被@Component修饰的类

>>>> findCandidateCoponents(base Package);

>>>> registerBeanDefinition(definitionHolder, this.registry);

// 处理@Import

>> ConfigurationClassParser#processImports

// im 并不会将bean注册到容器plements ImportSelector

>>> selector.selectImports(currentSourceClass.getMetadata());

// 处理@Bean ConfigurationClass 缓存beanMethods

>>>ConfigurationClass#addBeanMethod

// 回到processConfigBeanDefinitions

>ConfigurationClassPostProcessor#processConfigBeanDefinitions

// 注册bean到容器

>>> this.reader.loadBeanDefinitions(configClasses);

>>ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurati

onClass

// 注册 实现了ImportSelector的bean

>>> registerBeanDefinitionForImportedConfigurationClass(configClass);

// 方法bean 注册到容器

>>> loadBeanDefinitionsForBeanMethod(beanMethod);

// @ImportResource("spring.xml") 配置的bean注册到容器

loadBeanDefinitionsFromImportedResources(configClass.getImportedResources(

));

// 实现 ImportBeanDefinitionRegistrar的 bean 注册到容器

>>> loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionR

egistrars());

3.bean的依赖注入原理

查找方式:

byType

byName

注入方式: field

反射的方式,field.set(obj,value)

constructor

不配置 @Autowired情况下

多构造器时,有无参构造器,则调用无参构造器,若没有无参构造器,当剩余构造器大于 1个时,抛异常,当只有一个时,会执行此构造器

当只有一个有参构造器时,会执行此构造器

当该bean的beanDefinition设置了AutowireMode为3后,则会选择构造器贪婪模式,执行参数最多的构造器(前提:构造参数类型都是bean类型)

@Component

public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory

beanFactory) throws BeansException {

AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)

beanFactory.getBeanDefinition("userServiceImpl");

beanDefinition.setAutowireMode(3);//构造器贪婪模式

}

}

setter方法

不配置 @Autowired情况下 通过设置AutowireMode为1或者2,会调用setter方法,通过setter方法注入bean

AutowireCapableBeanFactory类

//没有外部定义的自动装配

int AUTOWIRE_NO = 0;

//基于规范的setter方法名调用,比如setUserDao(UserDao userDao)

//---setUserDao---bat.ke.qq.com.dao.UserDao@64cd705f

int AUTOWIRE_BY_NAME = 1;

/**

*基于setter方法的参数类型调用,set开头即可,比如

* ---setUserDao---bat.ke.qq.com.dao.UserDao@63355449

* ---setUserDaoxxxx---bat.ke.qq.com.dao.UserDao@63355449

* ---setxxxxxxUserDao---bat.ke.qq.com.dao.UserDao@63355449

**/

int AUTOWIRE_BY_TYPE = 2;

//自动装配最贪婪的构造函数

int AUTOWIRE_CONSTRUCTOR = 3;

今天就写到这里了,太累了。头发又少了几根,啃了一阵子spring源码,今天才敢写一点东西,希望对大家有帮助,最少也能理清一下。

创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

下篇文章我准备整理一篇《Bean的生命周期》不知道大家是否感兴趣,也可以评论告诉我。

如果本篇有任何错误,请批评指教,不胜感激 !

联系我/公众号(java耕耘者)一个每天吃饭睡觉打豆豆写代码的人。

Spring IoC源码分析_第3张图片

你可能感兴趣的:(Spring IoC源码分析)