用於標識一個類爲配置類,與xml配置效果相似html
public class TestApplication { public static void main(String args[]) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); } } @Configuration public class AppConfig { @Bean public A a(){ return new A(); } @Bean public B b(){ return new B(); } } public class A { public A(){ System.out.println("Call A constructor"); } } public class B { public B(){ System.out.println("Call B constructor"); } }
上面的例子應該是@Configuration最廣泛一種使用場景了,在@Configuration class下面配置@Bean method,用於想Spring Ioc容器注入bean.但其實咱們把AppConfig的@Configuration註解去掉,對應的Bean也是能夠被注入到容器中去的。java
咱們給AppConfig改寫一下,以下:ios
@Configuration @EnableAspectJAutoProxy public class AppConfig { @Bean public A a(){ b(); return new A(); } @Bean public B b(){ return new B(); }
再去執行TestApplication#main,那麼執行結果會是什麼樣呢?app
Call A constructor Call B constructor
嗯哼?按照Java的語法,B的構造函數應該是被調用了兩次啊?爲何只有輸出一句Call B constructor
?jvm
這其實就是@Configuration再發揮做用啦,不信你去掉@Configuration,再去運行一下,就會發現B的構造函數被執行了兩次。ide
官方給出了這樣一段解釋對於被@Configuration註解的類函數
In common scenarios,
@Beanmethods are to be declared within
@Configurationclasses, ensuring that 「full」 mode is always used and that cross-method references therefore get redirected to the container’s lifecycle management.
post
在通常狀況下,@Bean method 是被聲明在@Configuration類中的,以確保 full mode老是被使用,而且跨方法的引用會被重定向到容器生命週期管理。
this
原來Spring將被@Configuration註解的配置類定義爲full configuration, 而將沒有被@Configuration註解的配置類定義爲lite configuration。full configuration能重定向從跨方法的引用,從而保證上述代碼中的b bean是一個單例.spa
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { /** * 調用無參構造函數,實例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner * 同時會調用父類GenericApplicationContext無參構造函數實例化一個關鍵的工廠DefaultListableBeanFactory * 同時還會註冊一些開天闢地的後置處理器到beanDefinitionMap,這些後置處理器有bean工廠後置處理器;有bean後置處理器 */ this(); //將componentClasses註冊到beanDefinitionMap集合中去 register(componentClasses); refresh(); }
跟蹤refresh()
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //供上下文(Context)子類繼承,容許在這裏後置處理bean factory postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //按順序調用BeanFactoryPostProcessor,這裏的按順序僅實現了PriorityOrdered和Ordered的語意,未實現@Order註解的語意 //經過調用ConfigurationConfigPostProcessor#postProcessBeanDefinitionRegistry //解析@Configuration配置類,將自定義的BeanFactoryPostProcessor、BeanPostProcessor註冊到beanDefinitionMap //接着實例化全部(包括開天闢地)的BeanFactoryPostProcessor,而後再調用BeanFactoryPostProcessor#postProcessBeanFactory invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //按順序將BeanPostProcessor實例化成bean並註冊到beanFactory的beanPostProcessors, //這裏的按順序僅實現了PriorityOrdered和Ordered的語意,未實現@Order註解的語意 //由於BeanPostProcessor要在普通bean初始化()先後被調用,因此須要提早完成實例化並註冊到beanFactory的beanPostProcessors registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //註冊國際化相關的Bean initMessageSource(); // Initialize event multicaster for this context. //爲上下文註冊應用事件廣播器(用於ApplicationEvent的廣播),若是有自定義則使用自定義的,若是沒有則內部實例化一個 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. //註冊全部(靜態、動態)的listener,並廣播earlyApplicationEvents registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //實例化用戶自定義的普通單例Bean(非開天闢地的、非後置處理器) finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
跟蹤invokeBeanFactoryPostProcessors(beanFactory)
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
跟蹤invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); //此處調用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry, //解析配置類,爲配置中的bean定義生成對應beanDefinition,並注入到registry的beanDefinitionMap invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. //調用ConfigurationClassPostProcessor#postProcessBeanFactory加強配置類(經過cglib生成加強類,load到jvm內存, //設置beanDefinition的beanClass爲加強類) //爲何要加強配置類?主要是爲了讓@Bean生成的bean是單例, invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
跟蹤invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
private static void invokeBeanFactoryPostProcessors( Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { for (BeanFactoryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanFactory(beanFactory); } }
跟蹤ConfigurationClassPostProcessor#postProcessBeanFactory
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } //爲@Configuration註解的類生成加強類(若是有必要),並替換bd中的beanClass屬性, enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }
到了這一步謎底幾乎已經揭曉了,@Configuration class是經過加強來實現它的語義的。經過加強把跨方法的引用調用重定向到Spring生命週期管理.咱們近一步探索下這個enhanceConfigurationClasses方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); MethodMetadata methodMetadata = null; if (beanDef instanceof AnnotatedBeanDefinition) { methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); } if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived @Bean method // -> resolve bean class at this point... AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef; if (!abd.hasBeanClass()) { try { abd.resolveBeanClass(this.beanClassLoader); } catch (Throwable ex) { throw new IllegalStateException( "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); } } } //在ConfigurationClassUtils.checkConfigurationClassCandidate方法中會標記Configuration is full or lite if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) { if (!(beanDef instanceof AbstractBeanDefinition)) { throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass"); } else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause " + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " + "return type: Consider declaring such methods as 'static'."); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // Set enhanced subclass of the user-specified bean class Class<?> configClass = beanDef.getBeanClass(); //爲@Configuration註解的類生成加強類 Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass != enhancedClass) { if (logger.isTraceEnabled()) { logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName())); } beanDef.setBeanClass(enhancedClass); } } }
看到有那麼一句話Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
很明顯了,使用cglib技術爲config class生成一個enhancedClass,再經過beanDef.setBeanClass(enhancedClass);
修改beanDefinition的BeanClass屬性,在bean實例化階段,會利用反射技術將beanClass屬性對應的類實例化出來,因此最終實例化出來的@Configuration bean是一個代理類的實例。這裏稍微提一下爲何要使用cglib
,而不是jdk動態代理
,主要是由於jdk動態代理
是基於接口的,而這裏AppConfig並無實現任何接口,因此必須用cglib
技術。
被@Configuration 註解的類,是 full configuration class,該類會被加強(經過cglib
),從而實現跨方法引用調用被重定向到Spring 生命週期管理,最終保證@Bean method生成的bean是一個單例。
原文出處:https://www.cnblogs.com/think-in-java/p/11876997.html