- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
作者:京东科技 韩国凯 。
通过本文,读者可以0源码基础的初步学习spring源码,并能够举一反三从此进入源码世界的大米! 由于是第一次阅读源码,文章之中难免存在一些问题,还望包涵指正! 。
用一句话总结两者的区别就是: @Autowired会先通过类型注入,即byType,当存在有 多个类型 时会通过名称注入。@Resource则相反,会先通过名称注入,即byName, 当名称不存在或有多个名称时 会通过类型注入.
那么通过名称注入与通过类型注入有什么区别呢?
//创建接口
interface StuService{
String getName();
}
@Service
//Stu2实现接口并注册bean
class Stu2 implements StuService{
@Override
public String getName() {
return "stu2";
}
}
@Service
//Stu3实现接口并注册bean
class Stu3 implements StuService{
@Override
public String getName() {
return "stu3";
}
}
那么此时如果我们对 StuService 注入, @Autowired可以选择注入的类型就有两个,分别是 Stu2 与 Stu3 .
需要注意的是,类型有很多种选择:
例如,我们有获取session的工具类,需要将其注入到spring之中, 。
@Component
class SessionUtil{
public String getSession(){
return "session";
}
}
只有一个类,直接注册bean,使用时可以任意选择 。
@Autowired
SessionUtil sessionUtil;
此时@Autowired只有一个注册类型,直接注入.
例如上述 StuService 有多个实现类,每个实现类都注册了bean,因此@Autowired可以选择的类型就有两个.
@Autowired
StuService stu;
根据上述的@Autowired逻辑,此时有多个类型,那么会根据bean name查找,(即类名首字母小写的),发现 stu 没有对应的实现类, 。
此时会报错:
Field stu in com.example.demo.spring.Stu1 required a single bean, but 2 were found
只需要将 stu 替换成 stu2 或 stu3 即可完成注入.
继承和其他方式同时有多个bean注入时同理.
因此,@Autowired中类型的定义可以归结为: 当注册bean有多个时,类型为所有注册的bean,实现方式有:实现接口、继承、通过其他方式,例如xml配置注册bean或者@Bean注册.
@Autowired
SessionUtil sessionUtil;
例如上文中 Stu1 Stu2 都未指定bean名称,因此两者的bean名称分别为 stu1 stu2 .
当使用@Bean在方法上注册bean,此时名称为方法名称.
@Bean()
public Student getStudent(){
Student student = new Student();
student.setName("bob");
student.setId(26);
return student;
}
此时该bean名称为 getStudent .
同样,我们也可以注册bean时自定义bean名称 。
@Bean("stu1")
public Student getStudent(){
Student student = new Student();
student.setName("bob");
student.setId(26);
return student;
}
@Service("stu2")
class Stu2 implements StuService{
@Override
public String getName() {
return "stu2";
}
}
@Component("stu3")
class Stu3 implements StuService{
@Override
public String getName() {
return "stu3";
}
}
在引用时指定bean:
@Resource(name = "stu2")
private StuService stu1;
当我们使用@Resource时,会根据名称也就是 stu2 去查询,此时bean名称只有一个,查到返回 。
@Resource
private Stu3 stu2;
但是在执行时却发现报错:
Bean named 'stu2' is expected to be of type 'com.example.demo.spring.Stu3' but was actually of type 'com.example.demo.spring.Stu2'
这是因为只根据了bean名称去查询,却没有根据bean类型,查到的是 Stu2 类型的bean,但是期望的却是 Stu3 ,因此会发生类型不匹配.
spring的注册流程主要包含两个部分:
先了解一下几个概念:
存在于磁盘上的项目中用于描述一个bean的数据,可以是xml、properties、yaml等静态文件,也可以是各种注解描述的对应信息,例如@Service、@Component描述的一个bean的信息.
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<property name="id" value="1"/>
<property name="roleName" value="高级工程师"/>
<property name="note" value="重要人员"/>
</bean>
以上就是一个由xml定义的配置元数据.
在spring中,无论是那种配置元数据,最终都会转换为 BeanDefinition ,由BeanDefinition描述要生成并被引用的对象 ,可以理解为BeanDefinition就是bean的生成模板,或者是bean的说明书,按照BeanDefinition生成bean.
而将配置元数据转换为 BeanDefinition 的工作就是由 BeanDefinitionReader 完成的,对于不同的的配置元数据有不同的Reader完成对应的工作,例如有 XmlBeanDefinitionReader 读取xml配置信息, PropertiesBeanDefinitionReader 读取properties配置信息, AnnotatedBeanDefinitionReader 读取注解的配置信息.
BeanDefinitionReader的作用就是将磁盘上的文件信息或注解信息转化为内存中用于描述bean的BeanDefinition.
BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinitionRegistry中的一个个的BeanDefinition进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
<property name="maxWait" value="${jdbc.maxWait}"></property>
<property name="minIdle" value="${jdbc.minIdle}"></property>
<property name="driverClassName"
value="${jdbc.driverClassName}">
</property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
BeanFactoryPostProcessor就会对注册到BeanDefinitionRegistry中的BeanDefinition做最后的修改,替换$占位符为配置文件中的真实的数据.
一个存储BeanDefinition的地方,存储方式为KV值,key为beanName,value为BeanDefinition.
容器的启动阶段相对比较简单,首先会将存在于各处的磁盘上的配置元信息由各自的Reader读取到内存之中,转换成 BeanDefinition ,然后注册到 BeanDefinationRegistry 之中,最后由 BeanFactoryPostProcessor 进行修改与替换.
BeanFactory与FactoryBean的名字很像,但是确实两个不同的东西.
根据命名规则来看,BeanFactory是一个Factory,也就是一个存放bean的工厂,在创建bean完成后放到其中,使用是从其中获取.
而FactoryBean则是一个bean,只不过与不同的的bean不同的是他不仅可以创建本身类型的bean,也可以类似于Factory一样创建一层有包装的新的bean。这个Bean可以返回一个新的类型的bean,在返回之前也可以对其进行加工.
@Component
class FactoryBeanDemo implements FactoryBean<Student>{
@Override
public Student getObject() {
return new Student();
}
@Override
public Class<?> getObjectType() {
return Student.class;
}
}
创建一个FactoryBean只需要实现其接口,并实现其中的两个方法。当我们获取FactoryBean时,会返回其中 getObject() 方法返回的对象。而如果想要获取FactoryBean本身,只需要在bean name前加一个"&"符号即可.
@Resource()
private Object factoryBeanDemo;
@GetMapping("/getStu")
private String getBean(){
System.out.println(factoryBeanDemo.getClass());
return stu2.getName();
}
//输出结果
class com.example.demo.domain.Student
可以看到获取到的是Student类型.
class com.example.demo.spring.FactoryBeanDemo
将获取bean名称假“&”符号:
@Resource(name = "&factoryBeanDemo")
private Object factoryBeanDemo;
class com.example.demo.spring.FactoryBeanDemo
可以看到获取到的对象变成了FactoryBeanDemo本身.
在容器启动阶段,已经完成了bean的注册。如果该对象是配置成懒加载的方式,那么直到我们向Spring要依赖对象实例之前,其都是以BeanDefinitionRegistry中的一个个的BeanDefinition的形式存在,也就是Spring只有在我们第一次依赖对象的时候才开启相应对象的实例化阶段。而如果我们不是选择懒加载的方式,容器启动阶段完成之后,其中有一个步骤finishBeanFactoryInitialization(),在这一步将立即启动Bean实例化阶段,通过隐式的调用所有依赖对象的getBean方法来实例化所有配置的Bean,完成类的加载.
doGetBean():获取并返回bean 。
doGetBean()的主要流程有两个:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 1、查询缓存中是否存在,存在的话直接返回
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 根据缓存中的bean获取实例,主要是检测如果是FactoryBean类型,则获取其内部的getObject()的bean。(需要先了解FactoryBean的作用)
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//2、不存在则创建bean
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 2.1 尝试从父类的Factory加载bean
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
/*
* 2.2 获取RootBeanDefinition:首先会根据beanName获取BeanDefinition,然后将BeanDefinition转换为RootBeanDefinition
* BeanDefinition 接口的实现类有很多,通过不同方式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太相同。
最终,在通过 BeanDefinition 来创建 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。
所以,RootBeanDefinition 本质上是 Spring 运行时统一的 BeanDefinition 视图。
* */
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 2.3 初始化依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 2.4 创建实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//返回真正的bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName),
BeanDefinition 接口的实现类有很多,通过不同方式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太相同。 最终,在通过 BeanDefinition 来创建 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。所以,RootBeanDefinition 本质上是 Spring 运行时统一的 BeanDefinition 视图.
此处就是将各种BeanDefinition统一转换为spring能识别的RootBeanDefinition.
sharedInstance = getSingleton(beanName, () -> {
try {
//返回真正的bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
从 getSingleton() 方法中获取创建好的对象 。
//获取singletonFactory返回的结果
singletonObject = singletonFactory.getObject();
getSingleton() 方法中最主要的一次调用也就是从 singletonFactory 中获取对象,而获取对象的结果就是上面代码中传入的匿名工厂返回的结果,也就是 createBean(beanName, mbd, args) 。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 1.解析bean class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 2.准备覆盖的方法
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 3.尝试返回代理创建的Bean,这个作用就是查找bean中所有实现前置和后置处理器的接口,有没有手工创建然后返回的,代替了spring的创建bean的流程
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//4.真正创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
创建bean主要有以下几步:
以上流程都是获取bean前的流程或获取bean的准备,doCreateBean是真正的创建并填充bean的流程(去掉了一些不重要的代码).
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//1.通过反射创建实例化对象,并将其放入wraaper中。wraaper可以理解为bean的包装对象,里面是bean实例的,还有一些其他bean的属性方便使用
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
//2.允许后处理处理器修改合并后的bean定义,这里只是解析这些@Autowired @Value @Resource @PostConstruct等这些注解,并没有发生实际属性注入的动作
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//3.是否需要提前曝光,用来解决循环依赖时使用
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;
//4.将实例化完成成的bean填充属性
populateBean(beanName, mbd, instanceWrapper);
//5.调用初始化方法,例如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
//6.循环依赖检查
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);
}
}
}
}
}
// Register bean as disposable.
//7.注册bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
从上述流程中可以看到,我们创建一个bean主要有以下几个流程:
可以看到,经过以上的几个步骤,我们就获取到了一个实例bean.
其中最重要的三个方法:
总结来说,创建bean的流程就是先根据反射获取对象,然后填充对象的属性,初始化,最后将bean注册.
上文我们只粗略的讲解了创建bean的过程,并没有深入的查看源码是如何实现的,例如通过反射获取对象是怎么获取的,填充属性是如何填充的,下文将详细阐述2.2.5过程中在源码层面是如何构建的.
该方法通过反射获取实例化的空属性对象.
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//1.1解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//1.2确认public权限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//2.如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比较低
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
/*
* 3.如果args为空且方法已经被resolved,则会直接选择对应的构造方法
* mbd.resolvedConstructorOrFactoryMethod的赋值在下方【1】【2】的代码中赋值
* */
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
//4.自动装配的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
//5.是否有首选构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
//6.通过默认的无参构造函数
return instantiateBean(beanName, mbd);
}
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName),
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName),
选择AutowiredAnnotationBeanPostProcessor实现类:
其中重要的代码已贴出:
//1.遍历所有的构造方法
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
//2.查看当前构造方法是否有@Autowired注解
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//3.如果有@Autowired注解
if (ann != null) {
//4.如果已经有一个@Autowired注解,则说明存在多个@Autowired注解,则抛出异常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//5无参构造函数
else if (candidate.getParameterCount() == 0) {
//将其设置为默认构造函数
defaultConstructor = candidate;
}
}
//对上面的处理过程进行判断
//6.1先检查是否有@Autowired注解
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
//返回@Autowired注解的构造方法
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//6.2如果只有一个有参构造函数,则返回该有参函数
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//6.3对于非Kotlin类只会返回null,所以这里不会进入
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
//6.4对于不能识别的场景会进入到这里,例如有多个构造函数但是并没有指定@Autowired注解或者没有构造函数(java会帮我们生成一个无参的构造函数),返回null
candidateConstructors = new Constructor<?>[0];
}
2-5步会对所有的构造函数进行检查,并在检查完进行标记,并会在第6步对标记的结果进行返回,按照ifelse判断顺序主要分为以下几种情况:
在获取到需要的构造函数后,会进行标记,下次不用再次解析可以直接选用那个构造函数,即上文的第4步 。
我们查看代码发现,无论第4步返回什么结果,最终会执行以下两个方法:
autowireConstructor()与instantiateBean() 。
两者都会调用 。
instantiate() 方法 。
最终都会执行以下这个方法 。
BeanUtils.instantiateClass(constructorToUse) 。
也就是如下的代码 。
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
return ctor.newInstance(argsWithDefaultValues);
其中最重要的一句:
return ctor.newInstance(argsWithDefaultValues),
可以发现,也就是这里通过反射的方式创建了一个空属性对象,并一层层返回,直到后面的属性装配等过程,可以说这里就是bean加载过程的源头.
该方法主要解析该bean所相关的注解,例如属性有@Resource,bean中@PostConstruct注解都会被解析.
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
processor主要有两个实现类:
这里需要注意的是,该方法只是会解析并不会真正的进行注入,因为学习意义不大,并不在赘述.
//遍历所有的属性
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
//对属性进行装填
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
其中 bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName) 有几个实现方法,比较重要的是:
两者最终都会进入如下方法:
//判断要注入的是属性还是方法
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
//如果是属性的话则直接注入
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
//否则通过反射注入
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
理解起来比较简单,判断是方法注入还是属性注入,在注入时注入的对象为:
getResourceToInject(target, requestingBeanName) 。
找到 ResourceElement 的实现方法中 getResource() 方法:
返回了 autowireResource(this.resourceFactory, element, requestingBeanName) 。
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
autowiredBeanNames = new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
else {
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
在这个方法中,无论是if还是else,最终都会调用 。
getBean(name, element.lookupType)
也就是我们bean注入的入口,这个过程很像递归,在我们创建bean时,如果发现我们有依赖的其他bean,那么就会去创建依赖的bean,如果依赖的bean还有其依赖的属性则又会去创建被依赖的属性,只到最终全部创建完成,返回一开始想要创建的bean.
在该方法中,会对已经填充过属性的bean进行初始化:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//对bean的前置处理,其中@PostConstruct就在此步骤中
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用初始化方法如果bean实现了InitializingBean接口,则先执行InitializingBean接口的afterPropertiesSet方法,然后执行xml或注解设置的init-method方法。
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//对bean进行后置处理,对象的代理发生在此步骤中
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
在初始化bean的时候,主要分为三个部分,分别是 applyBeanPostProcessorsBeforeInitialization、invokeInitMethods、applyBeanPostProcessorsAfterInitialization ,分别对应于初始化的前置处理、自定义init方法、后置处理.
applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization 两个方法的大概逻辑就是获取获取所有实现其接口的类,然后执行其中被覆盖的方法.
常用的注解执行顺序如下:
并且在代码中可以看到,前置处理与后置处理都可以改变bean.
在容器启动阶段我们讲到BeanFactoryPostProcessor,这里我们讲到BeanPostProcessor,那么BeanFactoryPostProcessor 和 BeanPostProcessor 有什么区别呢?
BeanFactoryPostProcessor存在于容器启动阶段,而BeanPostProcessor存在于对象实例化阶段,BeanFactoryPostProcessor关注对象被创建之前那些配置的修改,而BeanPostProcessor阶段关注对象已经被创建之后的功能增强,替换等操作,这样就很容易区分了。 BeanPostProcessor与BeanFactoryPostProcessor都是Spring在Bean生产过程中强有力的扩展点。Spring中著名的AOP(面向切面编程),其实就是依赖BeanPostProcessor对Bean对象功能增强的.
BeanFactoryPostProcessor主要用于解决实例化之前,对实例的属性进行拓展,而BeanPostProcessor是在实例化之后对对象做的拓展.
用简单的话描述一下,创建一个bean的过程大概包括三部分:
applyBeanPostProcessorsAfterInitialization
的步骤中。 通过以上的步骤,就可以获得我们可以正常使用的一个bean.
最后此篇关于0源码基础学习Spring源码系列(一)——Bean注入流程的文章就讲到这里了,如果你想了解更多关于0源码基础学习Spring源码系列(一)——Bean注入流程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我尝试阅读有关 Spring BOM、Spring Boot 和 Spring IO 的文档。 但是没有说明,我们应该如何一起使用它们? 在我的项目中,我们已经有了自己的 Parent POM ,所以
我正在开发的很酷的企业应用程序正在转向 Spring。这对所有团队来说都是非常酷和令人兴奋的练习,但也是一个巨大的压力源。我们所做的是逐渐将遗留组件移至 Spring 上下文。现在我们有一个 huuu
我正在尝试使用 @Scheduled 运行 Spring 批处理作业注释如下: @Scheduled(cron = "* * * * * ?") public void launchMessageDi
我对这两个概念有点困惑。阅读 Spring 文档,我发现,例如。 bean 工厂是 Spring 容器。我还读到“ApplicationContext 是 BeanFactory 的完整超集”。但两者
我们有一个使用 Spring BlazeDS 集成的应用程序。到目前为止,我们一直在使用 Spring 和 Flex,它运行良好。我们现在还需要添加一些 Spring MVC Controller 。
假设我有一个类(class) Person带属性name和 age ,它可以像这样用 Spring 配置: 我想要一个自定义的 Spring 模式元素,这很容易做到,允许我在我的 Sp
如何在 Java 中以编程方式使用 Spring Data 创建 MongoDB 复合索引? 使用 MongoTemplate 我可以创建一个这样的索引:mongoTemplate.indexOps(
我想使用 spring-complex-task 执行我的应用程序,并且我已经构建了复杂的 spring-batch Flow Jobs,它执行得非常好。 你能解释一下spring批处理流作业与spr
我实现了 spring-boot 应用程序,现在我想将它用作非 spring 应用程序的库。 如何初始化 lib 类,以便 Autowiring 的依赖项按预期工作?显然,如果我使用“new”创建类实
我刚开始学习 spring cloud security,我有一个基本问题。它与 Spring Security 有何不同?我们是否需要在 spring boot 上构建我们的应用程序才能使用 spr
有很多人建议我使用 Spring Boot 而不是 Spring 来开发 REST Web 服务。我想知道这两者到底有什么区别? 最佳答案 总之 Spring Boot 减少了编写大量配置和样板代码的
您能向我解释一下如何使用 Spring 正确构建 Web 应用程序吗?我知道 Spring 框架的最新版本是 4.0.0.RELEASE,但是 Spring Security 的最新版本是 3.2.0
我如何才能知道作为 Spring Boot 应用程序的一部分加载的所有 bean 的名称?我想在 main 方法中有一些代码来打印服务器启动后加载的 bean 的详细信息。 最佳答案 如spring-
我有一个使用 Spring 3.1 构建的 RESTful API,也使用 Spring Security。我有一个 Web 应用程序,也是一个 Spring 3.1 MVC 应用程序。我计划让移动客
升级到 Spring 5 后,我在 Spring Rabbit 和 Spring AMQP 中遇到错误。 两者现在都设置为 1.5.6.RELEASE 有谁知道哪些版本应该与 Spring 5 兼容?
我现在已经使用 Spring Framework 3.0.5 和 Spring Security 3.0.5 多次了。我知道Spring框架使用DI和AOP。我还知道 Spring Security
我收到错误 Unable to Location NamespaceHandler when using context:annotation-config running (java -jar) 由
在 Spring 应用程序中嵌入唯一版本号的策略是什么? 我有一个使用 Spring Boot 和 Spring Web 的应用程序。 它已经足够成熟,我想对其进行版本控制并在运行时看到它显示在屏幕上
我正在使用 spring data jpa 进行持久化。如果存在多个具有相同名称的实体,是否有一种方法可以将一个实体标记为默认值。类似@Primary注解的东西用来解决多个bean的依赖问题 @Ent
我阅读了 Spring 框架的 DAOSupport 类。但是我无法理解这些 DAOSuport 类的优点。在 DAOSupport 类中,我们调用 getXXXTemplate() 方法来获取特定的
我是一名优秀的程序员,十分优秀!