BeanFactoryPostProcessor
在前面幾個章節,筆者有介紹過BeanFactoryPostProcessor,在spring在解析BeanDefinition之後,正式初始化bean之前,會回撥我們編寫的BeanFactoryPostProcessor介面,介面會傳入beanFactory物件,我們可以新增或修改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容器獲取userService對應的bean,但是列印bean的型別卻為OrderService。這段程式碼在實際開發中意義並不大,只是為了揭露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這三步。
我們在呼叫AnnotationConfigApplication的配置類建構函式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。
在呼叫建構函式AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)建立reader物件時,經過一系列的呼叫,會來到AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)方法,在這個方法裡會建立BeanDefinition並將beanName和BeanDefinition註冊到BeanDefinitionRegistry。
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實現又是呼叫DefaultListableBeanFactory類的registerBeanDefinition來完成。
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認為容器還沒完全啟動起來,不會有多個請求併發進行,所以不需要用synchronized,僅僅是簡單的在beanDefinitionMap建立對映,將新的beanName加入到beanDefinitionNames。而spring剛啟動時,在註冊beanDefinition時也是先使用<6>處的程式碼,直到spring生成一個bean呼叫markBeanAsCreated(String beanName)方法,之後又註冊beanDefinition,spring判斷alreadyCreated不為空,才呼叫<5>處的程式碼。
現在,我們來總結下,在我們用AnnotationConfigApplicationContext(Class<?>... componentClasses)建立ApplicationContext物件時,AnnotationConfigApplicationContext會先呼叫無參構造方法,在無參構造方法中進行AnnotatedBeanDefinitionReader的初始化,AnnotatedBeanDefinitionReader的構造引數需要傳入一個BeanDefinitionRegistry的實現,BeanDefinitionRegistry是用來註冊beanName和beanDefinition,而AnnotationConfigApplicationContext剛好實現了BeanDefinitionRegistry介面。
在建立AnnotatedBeanDefinitionReader物件的時候,會把ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor這些類構造成RootBeanDefinition並註冊到BeanDefinitionRegistry。而AnnotatedBeanDefinitionReader所需要的BeanDefinitionRegistry實現,即是我們最開始建立的AnnotationConfigApplicationContext物件,也就是說,之前說的那些BeanDefinition最終會註冊到AnnotationConfigApplicationContext。
然而,AnnotationConfigApplicationContext也並不是在自身完成beanName和BeanDefinition的註冊的,而是內部生成一個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。
最後,我們注意到一點,AnnotationConfigApplicationContext所繼承的GenericApplicationContext實現了一個設計模式——代理模式。
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; } }