1.写在前面
如果想系统的学习Spring的源码,我们需要了解就是Spring的中BeanDefinition,简单的说这个就是Spring的Bean的描述信息。因为的Spring中Bean的创建都是根据这个BeanDefinition这个来创建,也可以叫这个为Spring的Bean的建模对象。
2.官网对BeanDefinition的解释
当我们打开对应的Spring的官网,具体在Bean Overview中有关于BeanDefinition的介绍,具体如下图:
大概的意思就是,Spring IOC容器管理一个或多个Bean。 这些bean是使用您提供给容器的配置元数据创建的。在容器本身内,这些Bean定义表示为BeanDefinition对象,其中包含以下元数据:
- 包限定的类名:通常定义了Bean的实际实现类。
- Bean行为配置元素,用于声明Bean在容器中的行为(作用域,生命周期回调等)。
- 引用其他Bean进行其工作所需的Bean。 这些引用也称为协作者或依赖项。
- 要在新创建的对象中设置的其他配置设置,例如,池的大小限制或在管理连接池的Bean中使用的连接数。
简而言之:BeanDefinition的就是对Bean的信息进行描述,然后Spring会根据这个来创建对应的Bean。这里感觉java的中的Class很像,那么这里为什么不用Class呢?
3.为什么不用Class作为Bean的描述信息?
Class也就是我们通常说的类对象,就是一个普通的建模的对象,那么为什么Spring不能用Class来建立Bean呢?因为Class无法完成对Bean的信息的抽象,Class对象中只能描述方法和属性等等。而Spring中的Bean中有作用域,注入的信息,是否是懒加载。很明显Class不适合。这就是Spring不用Class作为Bean的描述信息的原因。
java实例化一个对象的基本过程:我们都知道jvm运行时class文件,当我们写一个java文件的时候,然后通过java的编译的命令,将这个文件编译成class文件,然后在加载到jvm中运行。具体如下图:
上面我们大概介绍了Spring 中的BeanDefinition,但是这些东西都是比较空洞的。我们需要从源码的角度查看Spring的BeanDefinition。
4.从源码的角度看BeanDefinition
在idea中我们打开我们已经编译好的Spring的源码,然后搜索对应的BeanDefinition的类,打开发现是一个接口,我们今天会介绍其中一个实现类。打开的代码如下:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//单例
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
//原型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
//设置Bean的类名
void setBeanClassName(@Nullable String beanClassName);
//获取Bean的类名
@Nullable
String getBeanClassName();
//设置作用域
void setScope(@Nullable String scope);
//获取对应的作用域
@Nullable
String getScope();
//设置为懒加载
void setLazyInit(boolean lazyInit);
//判断是否是懒加载
boolean isLazyInit();
//设置DependOn,对应的DependOn注解,或者是XML中的配置的
void setDependsOn(@Nullable String... dependsOn);
//获取DependOn设置的值
@Nullable
String[] getDependsOn();
//自动装配的候选的对象
void setAutowireCandidate(boolean autowireCandidate);
//是否是自动装配的候选对象
boolean isAutowireCandidate();
//设置主要的注入的对象
void setPrimary(boolean primary);
//获取是否主要的注入对象
boolean isPrimary();
//设置工厂Bean的名称
void setFactoryBeanName(@Nullable String factoryBeanName);
//获取工厂Bean的名称
@Nullable
String getFactoryBeanName();
//设置工厂方法的名称
void setFactoryMethodName(@Nullable String factoryMethodName);
//获取工厂方法的名称
@Nullable
String getFactoryMethodName();
//获取构造器的参数的值
ConstructorArgumentValues getConstructorArgumentValues();
//是否构造器参数有值
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
//获取属性
MutablePropertyValues getPropertyValues();
//是否有属性
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
//设置对应的初始化方法
void setInitMethodName(@Nullable String initMethodName);
//获取对应的初始化方法
@Nullable
String getInitMethodName();
//设置对应的销毁的方法
void setDestroyMethodName(@Nullable String destroyMethodName);
//获取对应的销毁的方法
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
//设置对应的描述信息
void setDescription(@Nullable String description);
//获取对应的描述信息
@Nullable
String getDescription();
ResolvableType getResolvableType();
//判断是否是单例
boolean isSingleton();
//判断是否是原型
boolean isPrototype();
//判断是否是抽象
boolean isAbstract();
//获取源的描述信息
@Nullable
String getResourceDescription();
//返回原始的BeanDefinition
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
上面的有些东西没回加上注释,是有些我自己也不清楚。希望大佬可以教教我。我们对上面的BeanDefinition进行一一解释,同时配上对应的应用。
4.1作用域,懒加载,BeanClassName
我们通过实现Spring中实现对应BeanFactoryPostProcessor
接口拿出对应的BeanDefinition信息。然后主要查看对应的作用域和懒加载以及BeanClassName的属性值。具体的代码如下:
package com.ys.beanDefinition.scopeOrLazyOrBeanClassName;
import org.springframework.stereotype.Component;
@Component
public class A {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
package com.ys.beanDefinition.scopeOrLazyOrBeanClassName;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ys.beanDefinition.scopeOrLazyOrBeanClassName")
public class AppConfig {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.ys.beanDefinition.scopeOrLazyOrBeanClassName;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("a");
System.out.println("scope:" + beanDefinition.getScope());
System.out.println("lazy:" + beanDefinition.isLazyInit());
System.out.println("beanClassName:" + beanDefinition.getBeanClassName());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
package com.ys.beanDefinition.scopeOrLazyOrBeanClassName;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext anno = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
运行结果如下:
可以看到我们Bean的默认的作用域是单例的模式,同时不是懒加载,同时BeanClassName的值就是Class的全类名,同时我们的使用对应的注解修改对应的值,具体如下图:
4.2DependsOn
DependsOn就表示:如果A DependsOn B,那么A创建好之前B已经创建好了。具体的代码如下:
package com.ys.beanDefinition.dependsOn;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
@Component
@DependsOn("b")
public class A {
public A() {
System.out.println("A.A");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
package com.ys.beanDefinition.dependsOn;
import org.springframework.stereotype.Component;
@Component
public class B {
public B() {
System.out.println("B.B");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
package com.ys.beanDefinition.dependsOn;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ys.beanDefinition.dependsOn")
public class AppConfig {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.ys.beanDefinition.dependsOn;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition aBeanDefinition = beanFactory.getBeanDefinition("a");
BeanDefinition bBeanDefinition = beanFactory.getBeanDefinition("b");
System.out.println("a.DependsOn:" + Arrays.toString(aBeanDefinition.getDependsOn()));
System.out.println("b.DependsOn:" + Arrays.toString(bBeanDefinition.getDependsOn()));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
package com.ys.beanDefinition.dependsOn;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext anno = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
运行的结果如下:
可以看到在A对象创建之前,先创建的是B对象,同时打印的依赖信息也是依赖B,如果没有依赖就是null。
4.3自动装配的候选对象和Primary。
还记得我们上篇博客中说道,如果是ByType的装配的模式,如果找到两个满足条件的类,会直接报错,因为Spring不知道装配那个,因为每一个对象都是自动装配的候选对象,如果我们将其中设置一个不是候选对象,就可以完成自动装配。或者将其中一个对象设置成主要装配的对象,也可以完成自动装配。具体的代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType">
<bean id="a" class="com.ys.beanDefinition.autowireCandidateOrPrimary.A"/>
<bean id="i1" class="com.ys.beanDefinition.autowireCandidateOrPrimary.I1"/>
<bean primary="true" autowire-candidate="false" id="i2" class="com.ys.beanDefinition.autowireCandidateOrPrimary.I2"/>
<bean id="myBeanFactoryBeanPostProcessor" class="com.ys.beanDefinition.autowireCandidateOrPrimary.MyBeanFactoryBeanPostProcessor"/>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
package com.ys.beanDefinition.autowireCandidateOrPrimary;
public class A {
private I i;
public void setI(I i) {
this.i = i;
}
public I getI() {
return i;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
package com.ys.beanDefinition.autowireCandidateOrPrimary;
public interface I {
}
- 1
- 2
- 3
- 4
- 5
package com.ys.beanDefinition.autowireCandidateOrPrimary;
public class I1 implements I {
}
- 1
- 2
- 3
- 4
- 5
package com.ys.beanDefinition.autowireCandidateOrPrimary;
public class I2 implements I {
}
- 1
- 2
- 3
- 4
- 5
package com.ys.beanDefinition.autowireCandidateOrPrimary;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryBeanPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition i1 = beanFactory.getBeanDefinition("i1");
BeanDefinition i2 = beanFactory.getBeanDefinition("i2");
System.out.println("i1:autowire-candidate:" + i1.isAutowireCandidate());
System.out.println("i1:primary:" + i1.isPrimary());
System.out.println("i2:autowire-candidate:" + i2.isAutowireCandidate());
System.out.println("i2:primary:" + i2.isPrimary());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
package com.ys.beanDefinition.autowireCandidateOrPrimary;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringXml.xml");
System.out.println(applicationContext.getBean(A.class).getI());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
运行的结果如下:
从上面的运行结果我们可以看到autowire-candidate的优先级要大于primary的优先级,因为我们在I2上同时加上了这个属性,我们将autowire-candidate的值设置成false,将primary的值设置成true,这个时候注入的是I2,所以autowire-candidate的优先级是大于primary的优先级。
4.4FactoryBean与FactoryMethod
根据对应的工厂bean和对应共产方法创建出对应的bean,具体的代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="serviceLocator" class="com.ys.beanDefinition.factoryBeanOrFactoryMethod.DefaultServiceLocator"/>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean id="myBeanFactoryBeanPostProcessor" class="com.ys.beanDefinition.factoryBeanOrFactoryMethod.MyBeanFactoryBeanPostProcessor"/>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
package com.ys.beanDefinition.factoryBeanOrFactoryMethod;
public interface ClientService {
}
- 1
- 2
- 3
- 4
- 5
package com.ys.beanDefinition.factoryBeanOrFactoryMethod;
public class ClientServiceImpl implements ClientService{
}
- 1
- 2
- 3
- 4
- 5
package com.ys.beanDefinition.factoryBeanOrFactoryMethod;
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.ys.beanDefinition.factoryBeanOrFactoryMethod;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryBeanPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition clientService = beanFactory.getBeanDefinition("clientService");
BeanDefinition defaultServiceLocator = beanFactory.getBeanDefinition("serviceLocator");
System.out.println("clientService:factoryBeanName:" + clientService.getFactoryBeanName());
System.out.println("clientService:factoryMethodName:" + clientService.getFactoryMethodName());
System.out.println("defaultServiceLocator:factoryBeanName:" + defaultServiceLocator.getFactoryBeanName());
System.out.println("defaultServiceLocator:factoryMethodName:" + defaultServiceLocator.getFactoryMethodName());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
package com.ys.beanDefinition.factoryBeanOrFactoryMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext xml = new ClassPathXmlApplicationContext("SpringFactoryBean.xml");
System.out.println(xml.getBean(ClientService.class));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
运行结果如下:
可以看到如果我们使用工厂bean和工厂方法创建出来的对象,这两个的值就不为null,如果不是就为null,这儿存的factoryBeanName的值是容器中的bean的ID的值。
4.5InitMethodName与DestroyMethodName
我们先看下官网中介绍的实现的方式有几种。具体如下图:
发现总共的方式有三种,同时执行的顺序是先注解的,然后是实现接口的,最后是XML的文件中,由于笔者的测试,这两个属性,只有在配置XML文件的时候才不会null,其他的时候都为null,其实也能理解,因为这三种方式,都可以存在,同时还有执行的顺序,如果都用这个两个属性存的话,就会将前面的给覆盖掉,具体的代码如下:
package com.ys.beanDefinition.initOrDestroy;
public class A implements InitializingBean, DisposableBean {
public A() {
System.out.println("A.A");
}
public void init() {
System.out.println("A.init");
}
public void destroy() {
System.out.println("A.destroy");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
package com.ys.beanDefinition.initOrDestroy;
public class B {
public B() {
System.out.println("B.B");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="a" class="com.ys.beanDefinition.initOrDestroy.A" init-method="init" destroy-method="destroy"/>
<bean id="b" class="com.ys.beanDefinition.initOrDestroy.B"/>
<bean id="myBeanFactoryBeanPostProcessor" class="com.ys.beanDefinition.initOrDestroy.MyBeanFactoryBeanPostProcessor"/>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
package com.ys.beanDefinition.initOrDestroy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryBeanPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition a = beanFactory.getBeanDefinition("a");
BeanDefinition b = beanFactory.getBeanDefinition("b");
System.out.println("a:InitMethodName:" + a.getInitMethodName());
System.out.println("a:DestroyMethodName:" + a.getDestroyMethodName());
System.out.println("b:InitMethodName:" + b.getInitMethodName());
System.out.println("b:DestroyMethodName:" + b.getDestroyMethodName());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
package com.ys.beanDefinition.initOrDestroy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext anno = new ClassPathXmlApplicationContext("SpringInit.xml");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
运行的结果如下:
可以看到我们其中存了对应方法名。
5.BeanDefinition的父接口AttributeAccessor
我们可以看到BeanDefinition继承了AttributeAccessor接口,那么这个接口中主要是干嘛的。具体的代码如下:
package org.springframework.core;
import org.springframework.lang.Nullable;
public interface AttributeAccessor {
void setAttribute(String name, @Nullable Object value);
@Nullable
Object getAttribute(String name);
@Nullable
Object removeAttribute(String name);
boolean hasAttribute(String name);
String[] attributeNames();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
可以看到上面只是定义了一些方法的增删查改,我们看不懂,这个时候我们需要找到对应的实现类。具体的类图如下:
可以看到AttributeAccessor接口的实现类是AttributeAccessorSupport类,打开对应的代码中发现主要通过一个LinkedHashMap的Map用来存对应的键值队,键是String类型,值是Object。这个是用来干嘛的呢?因为BeanDefinition不可能对Bean的信息所有的信息都抽象,就算能,后期也有可能回扩展,所以这儿用了一个Map来存没有对Bean信息的描述的值。我们可以打印看看这个值,具体的代码如下:
package com.ys.beanDefinition.Attribute;
import org.springframework.stereotype.Component;
@Component
public class A {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
package com.ys.beanDefinition.Attribute;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ys.beanDefinition.Attribute")
public class AppConfig {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.ys.beanDefinition.Attribute;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
public class Main {
public static void main(String[] args) {
GenericApplicationContext genericApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
BeanDefinition a = genericApplicationContext.getBeanDefinition("a");
System.out.println();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
运行的结果如下:
至于这个属性是什么意思后面会讲。
6.BeanDefinition的父接口BeanMetadataElement
我们打开对应的代码如下:
package org.springframework.beans;
import org.springframework.lang.Nullable;
public interface BeanMetadataElement {
@Nullable
default Object getSource() {
return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
我们可以写一个测试类看下打印出来的是什么东西,具体的代码如下:
package com.ys.beanDefinition.source;
import org.springframework.stereotype.Component;
@Component
public class A {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
package com.ys.beanDefinition.source;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ys.beanDefinition.source")
public class AppConfig {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.ys.beanDefinition.source;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
public class Main {
public static void main(String[] args) {
GenericApplicationContext genericApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
BeanDefinition a = genericApplicationContext.getBeanDefinition("a");
System.out.println("source:" + a.getSource());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
运行的结果如下:
可以看到存的是这个类的绝对路径的class文件。可能是为了后面反射创建对象用。
7.写在最后
本篇博客主要简单的介绍了一下BeanDefinition这个接口,以及他的父接口,下篇博客会讲下它对应的实现类。因为BeanDefinition对Spring来说太重要了,Spring创建Bean都是是根据这个来的。搞懂了这个,可以说Spring已经搞懂的大半了。