### BeanDefinition
BeanDefinition可以理解为底层源码级别的一个概念,也可以理解为Spring提供的一种API使用的方式。
```
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* 单例、原型标识符
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* 标识 Bean 的类别,
* 分别对应
* 用户定义的 Bean
* 来源于配置文件的 Bean、Spring 内部的 Bean
*
**/
int ROLE_APPLICATION = 0; // 表示用户定义的bean
int ROLE_SUPPORT = 1; // 暂时没发现哪里用到了
int ROLE_INFRASTRUCTURE = 2; // 表示框架层面的基础bean
// Modifiable attributes
/**
* parentName表示父BeanDefinition的名字
*/
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
/**
* 设置、返回 Bean 的 className
*/
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
/**
* 设置、返回 Bean 的作用域
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setScope(@Nullable String scope);
@Nullable
String getScope();
/**
* 设置、返回 Bean 是否懒加载
*/
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
/**
* BeanFactory会先初始化某个bean所依赖的bean
*/
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
/**
*
*设置、返回 Bean 是否可以自动注入。只对 @Autowired 注解有效
**/
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
/**
* tie-breaker:平局决胜,也就是在平局的时候选出来的胜利者
* 在进行自动注入时,如果找到了多个可注入bean,那么则选择被Primary标记的bean.
*/
void setPrimary(boolean primary);
boolean isPrimary();
/**
* 工厂bean名字,可以通过该bean中的某个方法得到一个bean对象
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
/**
*
* 工厂方法,可以是某个实例的方法(和factoryBean配合使用),也可以是静态方法
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
/**
* 构造方法参数值
*/
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
/**
* Return if there are property values values defined for this bean.
* @since 5.0.2
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* Set the name of the initializer method.
* @since 5.1
* 初始化方法
*/
void setInitMethodName(@Nullable String initMethodName);
/**
* Return the name of the initializer method.
* @since 5.1
*/
@Nullable
String getInitMethodName();
/**
* Set the name of the destroy method.
* @since 5.1
* 销毁回调方法
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/**
* Return the name of the destroy method.
* @since 5.1
*/
@Nullable
String getDestroyMethodName();
/**
* Set the role hint for this {@code BeanDefinition}. The role hint
* provides the frameworks as well as tools with an indication of
* the role and importance of a particular {@code BeanDefinition}.
* @since 5.1
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*
* 标志当前bean是用户创建的,还是基础框架中的
*/
void setRole(int role);
/**
* Get the role hint for this {@code BeanDefinition}. The role hint
* provides the frameworks as well as tools with an indication of
* the role and importance of a particular {@code BeanDefinition}.
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*/
int getRole();
/**
* Set a human-readable description of this bean definition.
* @since 5.1
* 人类可以看懂的描述
*/
void setDescription(@Nullable String description);
/**
* Return a human-readable description of this bean definition.
*/
@Nullable
String getDescription();
// Read-only attributes
/**
* Return a resolvable type for this bean definition,
* based on the bean class or other specific metadata.
* <p>This is typically fully resolved on a runtime-merged bean definition
* but not necessarily on a configuration-time definition instance.
* @return the resolvable type (potentially {@link ResolvableType#NONE})
* @since 5.2
* @see ConfigurableBeanFactory#getMergedBeanDefinition
* 用来解析一个Bean对应的类型上的各种信息,比如泛型
*/
ResolvableType getResolvableType();
/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
* @see #SCOPE_SINGLETON
*/
boolean isSingleton();
/**
* Return whether this a <b>Prototype</b>, with an independent instance
* returned for each call.
* @since 3.0
* @see #SCOPE_PROTOTYPE
*/
boolean isPrototype();
/**
* Return whether this bean is "abstract", that is, not meant to be instantiated.
*/
boolean isAbstract();
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Nullable
String getResourceDescription();
/**
* Return the originating BeanDefinition, or {@code null} if none.
* Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
```
我们可以通过定义一个BeanDefinition对象来表示定义了一个Bean:
```
public void TestAbstractBeanDefinition(){
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanDefinition.setBeanClass(User.class);
// 设置作用域
beanDefinition.setScope("prototype");
// 注册BeanDefinition
beanFactory.registerBeanDefinition("user", beanDefinition);
// 注册别名
beanFactory.registerAlias("user", "user1");
// 注册BeanPostProcessor
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
// 获取Bean对象
System.out.println(beanFactory.getBean("user"));
System.out.println(beanFactory.getBean("user"));
System.out.println(beanFactory.getBean("user1"));
// 根据类型获取beanNames
System.out.println(beanFactory.getBeanNamesForType(User.class));
}
```
### BeanDefinitionReader
BeanDefinitionRegistry 接口一次只能注册一个 BeanDefinition,而且只能自己构造 BeanDefinition 类来注册。BeanDefinitionReader 解决了这些问题,它一般可以使用一个 BeanDefinitionRegistry 构造,然后通过 loadBeanDefinitions()等方法,把 Resources 转化为多个 BeanDefinition 并注册到 BeanDefinitionRegistry。
#### loadBeanDefinitions()方法
```
/**
* 从指定的XML文件中加载bean定义
* @param encodedResource XML文件的资源描述符,允许指定用于解析文件的编码
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 获取xml文件的输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
```
### BeanDefinitionReader关系图

- ClassPathBeanDefinitionScanner:这个并不是BeanDefinitionReader,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition
- AbstractBeanDefinitionReader:实现了 EnvironmentCapable,提供了获取/设置环境的方法。定义了一些通用方法,使用策略模式,将一些具体方法放到子类实现。
- XmlBeanDefinitionReader:读取 XML 文件定义的 BeanDefinition
- PropertiesBeanDefinitionReader:可以从属性文件,Resource,Property 对象等读取 BeanDefinition
- GroovyBeanDefinitionReader:可以读取 Groovy 语言定义的 Bean
##### XmlBeanDefinitionReader使用
```
@Test
public void TestAbstractBeanDefinitionReader(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinitionReader reader =new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("spring.xml");
System.out.println(beanFactory.getBean("user"));
}
```
## BeanFactory
* Spring中比较核心的是BeanFactory的实现类DefaultListableBeanFactory

它实现了很多接口,表示,它拥有很多功能:
1. AliasRegistry:支持别名功能,一个名字可以对应多个别名
2. BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
3. BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
4. SingletonBeanRegistry:可以直接注册、获取某个单例Bean
5. SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
6. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
7. HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
8. DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能
9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
10. FactoryBeanRegistrySupport:支持了FactoryBean的功能
11. AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
12. AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames
13. ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory
14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
15. DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大
* DefaultListableBeanFactory.getBean
getBean 方法的真正实现是在 DefaultListableBeanFactory 的父类 AbstractBeanFactory 中,具体的实现方法是 doGetBean,本来想和大家子在这里聊一聊这个问题,但是发现这是一个非常庞大的问题,BeanFactory 和 FactoryBean 都还没和大家分享,所以这个话题我们还是暂且押后,一个点一个点来
* DefaultListableBeanFactory的简单使用
```
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
//bean工厂的bean属性处理容器,
// 说通俗一些就是可以管理我们的bean工厂内所有的beandefinition
// (未实例化)数据,可以随心所欲的修改属性。
//applicationContext.addBeanFactoryPostProcessor(new jackgreekBeanFactoryPostProcessor());
applicationContext.refresh();
DefaultListableBeanFactory listableBeanFactory =new DefaultListableBeanFactory();
listableBeanFactory.registerSingleton("user",new User());
Object user = listableBeanFactory.getBean("user");
System.out.println(user);
```
## FactoryBean
在我们的开发工作中应该都见过或使用过FactoryBean这个类,也许你会看成了BeanFactory这个类。FactoryBean和BeanFactory虽然长的很像,但是他们的作用确实完全不像。这里你可以想象一下,你会在什么样的场景下使用FactoryBean这个接口?FactoryBean是一个工厂Bean,可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。BeanFactory是Spring容器中的一个基本类也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,它对于Bean的创建有一个统一的流程。
```
public interface FactoryBean<T> {
//返回的对象实例
@Nullable
T getObject() throws Exception;
//Bean的类型
@Nullable
Class<?> getObjectType();
//true是单例,false是非单例 在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
default boolean isSingleton();
}
```
从上面的代码中我们发现在FactoryBean中定义了一个Spring Bean的很重要的三个特性:是否单例、Bean类型、Bean实例,这也应该是我们关于Spring中的一个Bean最直观的感受。虽然没有返回BeanName的值,但是我们也知道BeanName的值。下面我们来写一个关于FactoryBean的小例子。
```
@Test
public void testUserFactoryBean(){
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean("userFactoryBean"));//获得userFactoryBean.getObject()方法的对象
Object userFactoryBean = applicationContext.getBean("&userFactoryBean");//获得userFactoryBean对象
System.out.println(userFactoryBean);
}
```
* 控制台输出
```
Connected to the target VM, address: '127.0.0.1:52993', transport: 'socket'
User{id=1, name='jackgreek'}
com.wpp.service.impl.UserFactoryBean@6c64cb25
```
* 源码中getObjectForBeanInstance方法判断`&+name`获得baen对应的FactoryBean对象
```
// 判断beanInstance是不是FactoryBean
// 如果是FactoryBean
// 如果name是以&开头,那么则返回beanInstance
// 如果name不是以&开头,那么返回的是getObject方法中所返回的对象(注意如果是单例,则会进行缓存)
// 如果不是FactoryBean,那么返回的是beanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 如果是&userFactoryBean,那么则直接返回单例池(SingletonObjects)中的对象
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory .
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 如果beanInstance是FactoryBean,并且name也不是以&开头
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
// 从factoryBeanObjectCache中没有拿到则进行创建
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 调用getObject方法得到对象并放入factoryBeanObjectCache中
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
```
## ApplicationContext

ApplicationContext是个接口,可以把它理解为一个特殊的BeanFactory
1. HierarchicalBeanFactory:拥有获取父BeanFactory的功能
2. ListableBeanFactory:拥有获取beanNames的功能
3. ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
4. EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
5. ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
6. MessageSource:拥有国际化功能
有两个重要的实现类:
* AnnotationConfigApplicationContext
* ClassPathXmlApplicationContext
#### AnnotationConfigApplicationContext

AnnotationConfigApplicationContext类是我们使用最多的类
1. ConfigurableApplicationContext:继承了ApplicationContext接口,增加了,添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
2. AbstractApplicationContext:实现了ConfigurableApplicationContext接口
3. GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory beanFactory)
4. AnnotationConfigRegistry:可以单独注册某个为类为BeanDefinition(可以处理该类上的@Configuration注解,已经可以处理@Bean注解),同时可以扫描
5. AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能
#### ClassPathXmlApplicationContext

它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition
## BeanFactoryPostProcessor
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
* BeanFactoryPostProcessor的使用
```
public class jackgreekBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user");
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.add("id","2222");
System.out.println("postProcessBeanFactory"+beanFactory);
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("postProcessBeanDefinitionRegistry"+registry);
}
}
```
* 通过applicationContext添加BeanFactoryPostProcessor
```
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
//bean工厂的bean属性处理容器,
// 说通俗一些就是可以管理我们的bean工厂内所有的beandefinition
// (未实例化)数据,可以随心所欲的修改属性。
applicationContext.addBeanFactoryPostProcessor(new jackgreekBeanFactoryPostProcessor());
applicationContext.refresh();
applicationContext.getBean("user");
System.out.println( "通过Component注解注入的"+ applicationContext.getBean("user"));
DefaultListableBeanFactory listableBeanFactory =new DefaultListableBeanFactory();
listableBeanFactory.registerSingleton("user",new User());
User user = (User)listableBeanFactory.getBean("user");
System.out.println("通过BeanFactory注入的"+user);
```
* 通过查看控制台发现jackgreekBeanFactoryPostProcessor修改了通过Component注入的属性
```
"C:\Program Files\Java\jdk1.8.0_251\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:54435,suspend=y,server=n -javaagent:C:\Users\h5848\AppData\Local\JetBrains\IntelliJIdea2020.1\groovyHotSwap\gragent.jar -javaagent:C:\Users\h5848\AppData\Local\JetBrains\IntelliJIdea2020.1\captureAgent\debugger-agent.jar=file:/D:/Temp/capture.props -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_251\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_251\jre\lib\rt.jar;E:\Learning\spring\luban-spring-framework\jackgreek\out\production\classes;E:\Learning\spring\luban-spring-framework\jackgreek\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-core\build\libs\spring-cglib-repack-3.3.0.jar;E:\Learning\spring\luban-spring-framework\spring-core\build\libs\spring-objenesis-repack-3.1.jar;E:\Learning\spring\luban-spring-framework\spring-jdbc\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-jdbc\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-context\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-context\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-aop\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-aop\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-web\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-web\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-oxm\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-oxm\out\production\resources;C:\Users\h5848\.m2\repository\org\mybatis\mybatis-spring\2.0.5\mybatis-spring-2.0.5.jar;C:\Users\h5848\.m2\repository\mysql\mysql-connector-java\5.1.44\mysql-connector-java-5.1.44.jar;C:\Users\h5848\.m2\repository\org\mybatis\mybatis\3.4.5\mybatis-3.4.5.jar;C:\Users\h5848\.m2\repository\org\aspectj\aspectjrt\1.9.5\aspectjrt-1.9.5.jar;C:\Users\h5848\.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar;C:\Users\h5848\.m2\repository\javax\annotation\javax.annotation-api\1.2\javax.annotation-api-1.2.jar;C:\Users\h5848\.m2\repository\junit\junit\4.10\junit-4.10.jar;E:\Learning\spring\luban-spring-framework\spring-tx\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-tx\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-beans\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-beans\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-core\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-expression\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-expression\out\production\resources;E:\Learning\spring\luban-spring-framework\spring-jcl\out\production\classes;E:\Learning\spring\luban-spring-framework\spring-jcl\out\production\resources;C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar" com.wpp.beanFactoryTest
Connected to the target VM, address: '127.0.0.1:54435', transport: 'socket'
postProcessBeanDefinitionRegistryorg.springframework.beans.factory.support.DefaultListableBeanFactory@711f39f9: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,appConfig]; root of factory hierarchy
postProcessBeanFactoryorg.springframework.beans.factory.support.DefaultListableBeanFactory@711f39f9: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,appConfig,user,queryUserService,userService,messageSource]; root of factory hierarchy
通过Component注解注入的User{id=2222, name='jackgreek'}
通过BeanFactory注入的User{id=1, name='jackgreek'}
Disconnected from the target VM, address: '127.0.0.1:54435', transport: 'socket'
Process finished with exit code 0
```

Spring源码学习之概念详解(一)