BeanFactoryPostProcessor
在前面幾個章節,筆者有介紹過BeanFactoryPostProcessor接口,在spring在解析BeanDefinition之后,根據BeanDefinition初始化bean之前,會回調我們編寫的BeanFactoryPostProcessor實現類並調用postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,spring會通過這個方法傳入一個ConfigurableListableBeanFactory對象,我們可以對這個bean工廠對象新增或修改BeanDefinition。spring初始化bean一個典型的流程,就是根據我們標記在類上的@Component生成一個BeanDefinition,BeanDefinition中包含這個類的class對象,然后根據class對象生成實例。如果我們編寫兩個Service:UserService和OrderService,並在類上標注@Component,再編寫一個BeanFactoryPostProcessor接口,在接口中我們拿到UserService的BeanDefinition,並修改class為OrderService,那么我們從spring容器中獲取userService這個bean,它的類型是UserService呢還是OrderService呢?來看下面的示例:
package org.example.service;
import org.springframework.stereotype.Component;
@Component
public class OrderService {
}
package org.example.service;
import org.springframework.stereotype.Component;
@Component
public class UserService {
}
在Test1BeanFactoryPostProcessor類中,我們獲取userService的BeanDefinition,並打印它的class對象,這里應該是UserService,然后我們再設置BeanDefinition的class為OrderService
Test1BeanFactoryPostProcessor.java
package org.example.service;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class Test1BeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) beanFactory.getBeanDefinition("userService");
System.out.println("UserService beanDefinition class:" + beanDefinition.getBeanClass());
beanDefinition.setBeanClass(OrderService.class);
}
}
MyConfig.java
package org.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.example.service")
public class MyConfig {
}
測試用例:
@Test
public void test01() {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println("userService class:" + ac.getBean("userService").getClass());
}
運行結果:
UserService beanDefinition class:class org.example.service.UserService userService class:class org.example.service.OrderService
可以看到,spring容器會回調我們編寫的bean工廠后置處理器BeanFactoryPostProcessor實現類Test1BeanFactoryPostProcessor ,在回調方法中,我們可以從bean工廠獲取spring容器已經解析的UserService對應的BeanDefinition對象,打印這個BeanDefinition對象的class對象也確實是UserService的class對象,之后我們修改UserService對應的BeanDefinition的class對象為OrderService的class對象,之后我們從spring容器獲取beanName為userService的bean可以看到bean的實現類已經被替換成OrderService對象。這也驗證筆者之前所說的一個事實,BeanFactoryPostProcessor的回調時機,是在spring容器將類解析為BeanDefinition之后,及根據BeanDefinition生成bean之前。當然,這段代碼在實際開發中意義並不大,這里只是為了揭露spring的實現。
那么筆者這里有個疑問,spring是在何時解析BeanDefinition?何時回調BeanFactoryPostProcessor?何時初始化bean?回顧測試用例test01的兩行代碼,我們可以確定,前面的解析、回調、初始化一定是在test01里兩句代碼的某一句完成的,那么究竟是那一句呢?是創建應用上下文,還是打印userService對應的class對象呢?
為了定位上面的問題,我們對UserService和OrderService稍作修改,我們在兩個類的構造函數中增加打印:
public class UserService {
public UserService() {
System.out.println("UserService init...");
}
}
public class OrderService {
public OrderService() {
System.out.println("OrderService init...");
}
}
測試用例:
@Test
public void test02() {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
}
運行結果:
UserService beanDefinition class:class org.example.service.UserService OrderService init... OrderService init...
結果打印了兩次OrderService構造函數的內容,一次spring根據OrderService對應的BeanDefinition進行初始化,一次是我們修改userService對應的BeanDefinition的class為OrderService,spring根據class進行初始化。而test02只有一行初始化應用上下文的代碼,至此我們可以確定,spring的解析BeanDefinition、回調BeanFactoryPostProcessor、初始化bean都在初始化應用上下文完成。當然,spring的應用上下文實現,有:AnnotationConfigApplication、ContextClassPathXmlApplicationContext……等等,但大部分的應用上下文實現都是在初始化的時候完成解析BeanDefinition、回調BeanFactoryPostProcessor、初始化bean這三步。
我們在調用應用上下文的構造函數AnnotationConfigApplicationContext(Class<?>... componentClasses)時,這個函數內部會先調用默認的無參構造方法,初始化reader和scanner兩個對象。調用完默認構造方法后,接着調用register(Class<?>... componentClasses)將我們的配置類注冊進reader,這一步就會根據配置類生成BeanDefinition並注冊進spring容器,之后調用繼承自父類AbstractApplicationContext的refresh()方法。
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
……
}
於是我們進入到AbstractApplicationContext的refresh()方法,這個方法首先在<1>處調用obtainFreshBeanFactory()獲取一個beanFactory對象,在<2>、<3>會把beanFactory作為參數傳入其他方法,<2>處我們單看方法名invokeBeanFactoryPostProcessors可以知道這里是調用BeanFactoryPostProcessor接口,我們之前編寫的BeanFactoryPostProcessor實現類,就是在<2>處進行回調。<3>處單看方法名不太好理解,但如果看注釋就可以知道,初始化“剩余且非懶加載”的單例對象,換言之:我們的dao、service、controller都是在這一層完成bean的初始化以及屬性注入。這里的“剩余”很有意思,當我們基於spring框架進行開發,大部分的bean都是單例對象,包括我們之前的配置類(MyConfig)、BeanFactoryPostProcessor在spring容器中都會有對應的BeanDefinition和bean,我們知道要調用一個類的方法,首先要有那個類的對象,在<2>處的invokeBeanFactoryPostProcessors可以回調我們編寫的BeanFactoryPostProcessor實現類,說明在<2>處就已經進行一部分bean的初始化了,這部分bean就包含了BeanFactoryPostProcessor的實現類。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
……
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
……
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//<1>
……
try {
……
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);//<2>
……
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);//<3>
……
}
catch (BeansException ex) {
……
}
finally {
……
}
}
}
……
}
我們總結一下,當我們調用AnnotationConfigApplicationContext(Class<?>... componentClasses)構造函數時,會先初始化reader和scanner兩個對象,然后將配置類注冊到reader后,再調用refresh()進行BeanDefinition的解析、單例bean的實例化。
現在,我們來逐行分析AnnotationConfigApplicationContext(Class<?>... componentClasses)這個構造函數,首先這個構造函數會調用默認構造函數,進行reader和scanner的初始化,AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner接受一個BeanDefinitionRegistry接口類型的參數,而AnnotationConfigApplicationContext本身則實現了BeanDefinitionRegistry接口。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
從接口名BeanDefinitionRegistry本身我們可以知道,這個接口是用來注冊BeanDefinition,而接口所要求的實現,從上至下允許我們建議beanName和BeanDefinition的映射關系、根據beanName移除BeanDefinition,根據beanName獲取BeanDefinition、獲取所有BeanDefinition對應的beanName,獲取BeanDefinition的數量,判斷beanName是否已被使用。BeanDefinition之於beanName就如bean之於beanName一樣,一個BeanDefinition至少有一個beanName,同理一個bean至少有一個beanName,因為BeanDefinition和bean都可以有別名。
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
AnnotatedBeanDefinitionReader之所以要傳入一個BeanDefinitionRegistry進行初始化,是因為在初始化AnnotatedBeanDefinitionReader對象時會把一些基礎BeanDefinition注冊到BeanDefinitionRegistry,因為AnnotationConfigApplicationContext這個類本身就實現了BeanDefinitionRegistry接口,所以AnnotatedBeanDefinitionReader會把BeanDefinition注冊到AnnotationConfigApplicationContext,spring容器可以根據這些基礎的BeanDefinition初始化一些基礎組件,這些組件在spring容器同樣作為bean對象而存在,這些基礎組件有的可以根據我們給定的類路徑將我們的類解析為BeanDefinition,有的可以根據@Autowired、@Inject、@Resource注解注入一個bean所依賴的bean。
當把一個BeanDefinitionRegistry對象傳給AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)構造函數創建reader對象時,在下面代碼<1>處對象會用字段registry指向傳入的BeanDefinitionRegistry對象,方便后續向BeanDefinitionRegistry對象注冊BeanDefinition。
public class AnnotatedBeanDefinitionReader {
……
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;//<1>
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
……
}
之后會執行AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)方法,這個方法就是先前說的會注冊多個基礎BeanDefinition到BeanDefinitionRegistry,可以看到這里會調用registerPostProcessor方法在BeanDefinitionRegistry建立beanName和BeanDefinition的映射。
public abstract class AnnotationConfigUtils {
……
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
……
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);//<1>
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));//<2>
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);//<3>
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));//<4>
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);//<5>
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));//<6>
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);//<7>
return new BeanDefinitionHolder(definition, beanName);
}
……
}
- 代碼<1>創建一個ConfigurationClassPostProcessor的BeanDefinition,這個類實現了BeanDefinitionRegistryPostProcessor接口,它會根據我們指定的掃描路徑去掃描組件。
- 代碼<3>創建一個AutowiredAnnotationBeanPostProcessor的BeanDefinition,這個類主要是用於注入標記了@Autowired和@Inject的屬性。
- 代碼<5>創建一個ConfigurationClassPostProcessor的BeanDefinition,這個類主要是用於注入標記了@Resource的屬性。
- 在代碼的<2>、<4>、<6>會調用registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)將beanName和BeanDefinition注冊到BeanDefinitionRegistry。
- 代碼<7>處接收到registry、beanName、BeanDefinition會調用registry的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法,對beanName和BeanDefinition進行映射。
上面的registry是我們之前創建的AnnotationConfigApplicationContext對象,如果我們查看AnnotationConfigApplicationContext的registerBeanDefinition方法,會發現這個方法是繼承父類GenericApplicationContext,而GenericApplicationContext又是使用代理模式,將registerBeanDefinition方法的工作交由同樣實現了BeanDefinitionRegistry接口的DefaultListableBeanFactory類來完成。
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
……
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
……
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
……
}
下面,我們再來看看DefaultListableBeanFactory的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true;
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** Map from bean name to merged RootBeanDefinition. */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/** Names of beans that have already been created at least once. */
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
……
public boolean isAllowBeanDefinitionOverriding() {
return this.allowBeanDefinitionOverriding;
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");//<1>
……
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {//<2>
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
……
this.beanDefinitionMap.put(beanName, beanDefinition);//<3>
}
else {//<4>
if (hasBeanCreationStarted()) {//<5>
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {//<6>
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
……
}
protected boolean hasBeanCreationStarted() {
return !this.alreadyCreated.isEmpty();
}
protected void markBeanAsCreated(String beanName) {//<7>
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
……
}
- 在<1>處判斷beanName和beanDefinition都不為空,因為這兩者只要有其一為空都是不符合常理的,我們不會指定一個bean的名字為null,而beanDefinition如果為null,那就更不會生成bean。
- 如果beanName已存在對應的beanDefinition,就會進入到<2>處的分支。這里會調用isAllowBeanDefinitionOverriding()方法判斷是否允許重載beanDefinition,isAllowBeanDefinitionOverriding()返回allowBeanDefinitionOverriding字段,這個字段默認為true,即允許beanName重復,會接着執行到<3>處,為beanName和新的beanDefinition在beanDefinitionMap建立映射關系。
- 如果beanName在beanDefinitionMap不存在映射,則會進入到分支<4>處。
- 到達<4>處的分支后,會先進行hasBeanCreationStarted()的判斷,從這個方法名我們可以知道,這個是判斷是否存已被創建的bean,而hasBeanCreationStarted()方法的實現也是非常簡單的,如果alreadyCreated不為空則返回true,事實上,當spring創建一個bean時,會調用<7>處的markBeanAsCreated(String beanName)方法,將beanName加入到alreadyCreated集合里。
- 如果spring容器中存在已創建的bean,在注冊beanDefinition會進入到<5>處對beanDefinitionMap加上同步鎖,然后在建立beanName和beanDefinition在beanDefinitionMap的映射,並創建一個updatedDefinitions對象,將舊的beanDefinitionNames列表和新的beanName加入到updatedDefinitions,再更新beanDefinitionNames指向updatedDefinitions。為什么spring會有這一步操作呢?因為即便spring容器初始化完畢,程序開始提供服務,依舊可以向容器注冊beanDefinition並獲取對應的bean。換句話說,你用spring寫了個電商系統,電商系統可以一邊向用戶提供下單服務,一邊注冊beanDefinition並生成對應的bean,甚至可以多線程注冊beanDefinition生成bean,所以才要對beanDefinitionMap加上同步鎖,而markBeanAsCreated(String beanName)里加上同步鎖也是同樣的道理。
- 如果在注冊beanDefinition時spring容器還沒有生成bean,則會調用<6>處的方法,這里並沒有用synchronized來防止多線程並發注冊,因為這個時候spring認為容器還沒完全啟動起來,不會有多個請求並發進行,所以不需要用分支<5>內的synchronized代碼塊來保證注冊BeanDefinition的線程安全性,僅僅是簡單的在beanDefinitionMap上建立beanName和BeanDefinition的映射,然后將新的beanName加入到beanDefinitionNames。
現在,我們來總結下,在我們用AnnotationConfigApplicationContext(Class<?>... componentClasses)創建ApplicationContext對象時,AnnotationConfigApplicationContext會先調用默認無參構造方法,在無參構造方法中進行AnnotatedBeanDefinitionReader的初始化,AnnotatedBeanDefinitionReader的構造參數需要傳入一個BeanDefinitionRegistry的實現,BeanDefinitionRegistry是用來注冊一些基礎的beanDefinition,而AnnotationConfigApplicationContext類實現了BeanDefinitionRegistry接口,將自身對象作為參數傳入到AnnotatedBeanDefinitionReader的構造函數初始化reader對象。在創建AnnotatedBeanDefinitionReader對象的時候,會把ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor這些類構造成RootBeanDefinition並注冊到BeanDefinitionRegistry。
然而,AnnotationConfigApplicationContext也並不是在自身完成beanName和BeanDefinition的映射關系,而是其父類GenericApplicationContext使用了代理模式在內部生成一個DefaultListableBeanFactory類型的引用,借助DefaultListableBeanFactory來完成beanName和BeanDefinition的映射建立。DefaultListableBeanFactory在注冊beanName和BeanDefinition的時候,會先判斷beanName和BeanDefinition是否為空,為空就要報錯,如果都不為空,再判斷beanName在DefaultListableBeanFactory中是否已存在對應的BeanDefinition,如果存在再判斷是否允許重載?默認是允許重載。如果已存在,且允許重載,則重新在DefaultListableBeanFactory的beanDefinitionMap建立映射,如果已存在卻不允許重載,則拋出異常。
如果beanName在注冊時不存在已對應的BeanDefinition,那就要分兩步判斷了,一種是spring容器已存在bean,另一種是還不存在bean,首先在AnnotatedBeanDefinitionReader內部注冊RootBeanDefinition的時候,走的是不存在bean的分支,也就是簡單的把beanName和BeanDefinition存到beanDefinitionMap,beanName加入到beanDefinitionNames集合。
如果是spring中已存在bean的情況,為了防止多線程進行BeanDefinition的注冊,spring對beanDefinitionMap加上同步鎖,在同步代碼塊中保存beanName和BeanDefinition在beanDefinitionMap上的映射,將beanName加入到beanDefinitionNames。
GenericApplicationContext實現了BeanDefinitionRegistry接口,GenericApplicationContext類中存在一個名為beanFactory的字段,類型是DefaultListableBeanFactory,在調用GenericApplicationContext實現自BeanDefinitionRegistry的方法,會轉而調用DefaultListableBeanFactory對應的方法。
public interface BeanDefinitionRegistry extends AliasRegistry {
……
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
……
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
……
}
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
……
}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
……
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
……
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
return this.beanFactory.getBeanDefinition(beanName);
}
……
}
而DefaultListableBeanFactory類本身也實現了BeanDefinitionRegistry,這就是典型的代理模式。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
……
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
……
return bd;
}
}
