# 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析) (2)

我们在xml中配置了2个类:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans "> <bean></bean> <bean></bean> </beans> @Controller @Data public class TestController { @Autowired private TestService testService; } @Service class TestService { }

测试代码:

package org.springframework.contextnamespace; @Slf4j public class MainClassForTestAnnotationConfig { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[]{"classpath:context-namespace-test-annotation-config.xml"},false); context.refresh(); Map<String, Object> map = context.getDefaultListableBeanFactory().getAllSingletonObjectMap(); log.info("singletons:{}", JSONObject.toJSONString(map)); List<BeanDefinition> list = context.getBeanFactory().getBeanDefinitionList(); MyFastJson.printJsonStringForBeanDefinitionList(list); Object testService = context.getBean(TestService.class); System.out.println("testService bean:" + testService); Object bean = context.getBean(TestController.class); System.out.println("testController bean:" + bean); } }

测试程序很简单,就是getBean来获取两个service,大家觉得注入会成功吗?

我们看答案吧:

testService bean:org.springframework.contextnamespace.TestService@236e3f4e

testController bean:TestController(testService=null)

可以看到,没注入,说明我们配置了@autowired,但是没生效。

怎么才能注入呢?很简单啊。在xml中配置如下元素即可:

<context:annotation-config></context:annotation-config>

这次再看测试代码的输出:

# 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

这次可以看到,已经注入了。

等价用法 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans "> //注释之,使用<bean>声明一个AutowiredAnnotationBeanPostProcessor <!--<context:annotation-config></context:annotation-config>--> <bean/> <bean></bean> <bean></bean> </beans>

测试:

# 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

元素解析

从ContextNamespaceHandler,我们可以找到该元素的解析类:

public void init() { ... registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); ... }

这个类很简单,所以这里直接一览全局:

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); // 这里,把支持的注解的解析代码全部注册到beanFactory // Obtain bean definitions for all relevant BeanPostProcessors. Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source); //检查有没有嵌套元素啥的,不用管 // Register component for the surrounding <context:annotation-config> element. CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); parserContext.pushContainingComponent(compDefinition); // Nest the concrete beans in the surrounding component. for (BeanDefinitionHolder processorDefinition : processorDefinitions) { parserContext.registerComponent(new BeanComponentDefinition(processorDefinition)); } // Finally register the composite component. parserContext.popAndRegisterContainingComponent(); return null; } }

这个解析类,独具一格,类层次也很简单,直接就实现了BeanDefinitionParser,不想前面那些类的层次那么复杂。这个类的重点方法是在:

AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);

这局呢,里面会注册各种注解的解析代码(一些beanPostProcessor)到beanFactory。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, Object source) { Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4); // 用于支持Configuration注解,注册了一个beanDefinition,其类别为BeanPostProcessor,具体bean class为 ConfigurationClassPostProcessor if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 用于支持Autowired注解,注册了一个beanDefinition,其类别为 BeanFactoryPostProcessor,具体bean class为 AutowiredAnnotationBeanPostProcessor if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 用于支持Required注解,注册了一个beanDefinition,其类别为BeanPostProcessor,具体bean class为 RequiredAnnotationBeanPostProcessor if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 用于支持JSR-250注解,注册了一个beanDefinition,其类别为BeanPostProcessor,具体bean class为 CommonAnnotationBeanPostProcessor // 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); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { ...支持jpa的相关代码 } return beanDefs; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpggws.html