spring 源码解读之标签解析与bean的注册


http://www.springframework.org/schema/p,获取到这个命名空间的处理类NamespaceHandler
命名空间的处理类特点都实现了NamespaceHandler接口
NamespaceHandler接口有三个方法:
init 完成标签元素解析类的注册
parse 解析
decorate 装饰BeanDefinitionHolder
4.在spring.handlers文件中,发现p标签和c标签的实现类
http://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
5.看p标签处理,实现类SimplePropertyNamespaceHandler

public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
		if (node instanceof Attr) {
			Attr attr = (Attr) node;
			String propertyName = parserContext.getDelegate().getLocalName(attr);
			String propertyValue = attr.getValue();
			MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues();
			if (pvs.contains(propertyName)) {
				parserContext.getReaderContext().error("Property '" + propertyName + "' is already defined using " +
						"both  and inline syntax. Only one approach may be used per property.", attr);
			}
			if (propertyName.endsWith(REF_SUFFIX)) {
				propertyName = propertyName.substring(0, propertyName.length() - REF_SUFFIX.length());
				pvs.add(Conventions.attributeNameToPropertyName(propertyName), new RuntimeBeanReference(propertyValue));
			}
			else {
				pvs.add(Conventions.attributeNameToPropertyName(propertyName), propertyValue);
			}
		}
		return definition;
	}

可以看出解析出propertyName与propertyValue 然后封装成PropertyValue,添加到MutablePropertyValues中
6.看c标签解析,实现类SimpleConstructorNamespaceHandler

public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
		if (node instanceof Attr) {
			Attr attr = (Attr) node;
			String argName = StringUtils.trimWhitespace(parserContext.getDelegate().getLocalName(attr));
			String argValue = StringUtils.trimWhitespace(attr.getValue());

			ConstructorArgumentValues cvs = definition.getBeanDefinition().getConstructorArgumentValues();
			boolean ref = false;

			// handle -ref arguments
			if (argName.endsWith(REF_SUFFIX)) {
				ref = true;
				argName = argName.substring(0, argName.length() - REF_SUFFIX.length());
			}

			ValueHolder valueHolder = new ValueHolder(ref ? new RuntimeBeanReference(argValue) : argValue);
			valueHolder.setSource(parserContext.getReaderContext().extractSource(attr));

			// handle "escaped"/"_" arguments
			if (argName.startsWith(DELIMITER_PREFIX)) {
				String arg = argName.substring(1).trim();

				// fast default check
				if (!StringUtils.hasText(arg)) {
					cvs.addGenericArgumentValue(valueHolder);
				}
				// assume an index otherwise
				else {
					int index = -1;
					try {
						index = Integer.parseInt(arg);
					}
					catch (NumberFormatException ex) {
						parserContext.getReaderContext().error(
								"Constructor argument '" + argName + "' specifies an invalid integer", attr);
					}
					if (index < 0) {
						parserContext.getReaderContext().error(
								"Constructor argument '" + argName + "' specifies a negative index", attr);
					}

					if (cvs.hasIndexedArgumentValue(index)) {
						parserContext.getReaderContext().error(
								"Constructor argument '" + argName + "' with index "+ index+" already defined using ." +
								" Only one approach may be used per argument.", attr);
					}

					cvs.addIndexedArgumentValue(index, valueHolder);
				}
			}
			// no escaping -> ctr name
			else {
				String name = Conventions.attributeNameToPropertyName(argName);
				if (containsArgWithName(name, cvs)) {
					parserContext.getReaderContext().error(
							"Constructor argument '" + argName + "' already defined using ." +
							" Only one approach may be used per argument.", attr);
				}
				valueHolder.setName(Conventions.attributeNameToPropertyName(argName));
				cvs.addGenericArgumentValue(valueHolder);
			}
		}
		return definition;
	}

同样它的实现逻辑与constructor-arg标签的解析类似

http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

http://www.test.com/schema/mytags.xsd=META-INF/mytags.xsd
2.

<?xml version="1.0" encoding="UTF-8"?>

	
		
			
			
			
		
	

3.spring.handlers定义标签解析类
http://www.test.com/schema/mytags=com.test.tag.TagsNamespaceHandler
4.

public class TagsNamespaceHandler extends NamespaceHandlerSupport {
    
    public void init() {
        this.registerBeanDefinitionParser("redis",
                new RedisBeanDifinitionParser());
    }

    @Override
    public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
        return super.decorate(node, definition, parserContext);
    }
}
public class RedisBeanDifinitionParser extends
        AbstractSingleBeanDefinitionParser {
    
    protected Class<?> getBeanClass(Element element) {
        return Jedis.class;
    }
    
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String ip = element.getAttribute("ip");
        String port = element.getAttribute("port");
        
        builder.addConstructorArgValue(ip);
        builder.addConstructorArgValue(Integer.parseInt(port));
    }
}

总结

1.spring标签解析分为默认标签解析与自定义标签解析
2.默认标签解析最常见的就是bean标签,次之为import标签等
3.bean标签解析先构建GenericBeanDefinition,然后将标签上的元素与子标签解析出来,为GenericBeanDefinition里的属性赋值
bean标签常见的元素有id,class,init-method,factory-bean,factory-method,lazy-init,depends-on,destroy-method,scope,primary等等
子标签有constructor-arg,property,lookup-method,replaced-method
4.GenericBeanDefinition中MutablePropertyValues,MethodOverrides,ConstructorArgumentValues,attributes三个重要的属性对应着property标签,lookup-method与replaced-method标签,constructor-arg标签,meta标签的解析与封装
5.创建完GenericBeanDefinition后,接着就是注册,注册时2个比较重要的容器是beanDefinitionMap,beanDefinitionNames
6.自定义标签解析首先是通过spring.handlers文件找到namespaceUri对应的解析类NameSpaceHandler
7.该解析类中有3个重要的方法
init 完成标签元素解析类的注册
parse 解析
decorate 装饰BeanDefinitionHolder
8.解析首先是创建注解扫描器
9.注解扫描器默认扫描的是类上包含@Component,@Service注解的类,并对其一些注解的支持,一并封装到ScannedGenericBeanDefinition中
10.完成@Component,@Service注解类的注册
11.完成默认标签与自定义标签解析后,spring注册了几个常见的BeanPostProcessor,如下
ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor
ConfigurationClassPostProcessor对@Configuration,@Component,@ComponentScan,@Import,@ImportResource,@Bean注解的支撑
AutowiredAnnotationBeanPostProcessor对@Autowired,@Value注解的支撑
CommonAnnotationBeanPostProcessor对@PostConstruct,@PreDestroy,@Resource注解的支撑
PersistenceAnnotationBeanPostProcessor对JPA的支撑