电脑装配网

Spring 注解@Configuration

 人阅读 | 作者lilintao | 时间:2023-08-25 00:34

@Configuration 平时我们主要的作用就是在方法上@bean用于自定义bean,注入到spring 容器中;注解有两个属性,value和proxyBeanMethods,我们主要说说,proxyBeanMethods。

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Configuration {@AliasFor(annotation = Component.class)String value() default "";boolean proxyBeanMethods() default true;}

1.proxyBeanMethods = true(默认值),则beanDefinition的configurationClass =full,否则configurationClass =lite;

ConfigurationClassUtils.java

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {//......省略其他代码........Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}else if (config != null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}else {return false;}// It's a full or lite configuration candidate... Let's determine the order value, if any.Integer order = getOrder(metadata);if (order != null) {beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;}

ConfigurationClassPostProcessor.java 的postProcessBeanFactory方法中调用enhanceConfigurationClasses()方法对configurationclass 进行增强;如果beanDefinition的configurationClass =full生成代理类。

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();for (String beanName : beanFactory.getBeanDefinitionNames()) {BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);AnnotationMetadata annotationMetadata = null;MethodMetadata methodMetadata = null;if (beanDef instanceof AnnotatedBeanDefinition) {AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;annotationMetadata = annotatedBeanDefinition.getMetadata();methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();}if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {// Configuration class (full or lite) or a configuration-derived @Bean method// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration// or component class without @Bean methods.AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;if (!abd.hasBeanClass()) {boolean liteConfigurationCandidateWithoutBeanMethods =(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));if (!liteConfigurationCandidateWithoutBeanMethods) {try {abd.resolveBeanClass(this.beanClassLoader);}catch (Throwable ex) {throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);}}}}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() || NativeDetector.inNativeImage()) {// nothing to enhance -> return immediatelyenhanceConfigClasses.end();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 classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass<?> configClass = beanDef.getBeanClass();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);}}enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();}

configurationClass =full时,会对bean 进行代理增强,因此调用方法时,都是通过代理从spring 的容器中获取,因此是每次调用的返回对象都是相同的;都则每次方法调用生成的都是一个新的对象

------------------------------------------------------------------

dome:

@Configuration(proxyBeanMethods = false)public class TeacherConfig { @Bean("teacher") public Teacher getTeacher(){ return new Teacher(); }}public class SpringDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args); StudentConfig studentConfig = context.getBean(StudentConfig.class); TeacherConfig teacherConfig = context.getBean(TeacherConfig.class); System.out.println("teacher:"+context.getBean(Teacher.class)); System.out.println("student:"+context.getBean(Student.class)); System.out.println("student:"+studentConfig.getStudent()); System.out.println("student:"+studentConfig.getStudent()); System.out.println("teacher:"+teacherConfig.getTeacher()); System.out.println("teacher:"+teacherConfig.getTeacher()); }}

执行结果:

teacher:com.ml.springdemo.Teacher@9573b3bstudent:com.ml.springdemo.Student@3d6300e8student:com.ml.springdemo.Student@3d6300e8student:com.ml.springdemo.Student@3d6300e8teacher:com.ml.springdemo.Teacher@1b822fccteacher:com.ml.springdemo.Teacher@24a1c17f

文章标签:

本文链接:『转载请注明出处』