这是一篇纯源码的文章,可能有些枯燥,希望大家喜欢。不废话
一、源码编译
1.下载:
git clone https://github.com/spring-projects/spring-framework.git 1
cd spring-framework/
2.编译:
先配置gradle编译环境
gradle -v
idea中配置gradle
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耕耘者)一个每天吃饭睡觉打豆豆写代码的人。