Spring实现解析默认标签的方法
发表于:2024-12-12 作者:千家信息网编辑
千家信息网最后更新 2024年12月12日,这篇文章主要讲解了"Spring实现解析默认标签的方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Spring实现解析默认标签的方法"吧!1、解析默
千家信息网最后更新 2024年12月12日Spring实现解析默认标签的方法
这篇文章主要讲解了"Spring实现解析默认标签的方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Spring实现解析默认标签的方法"吧!
1、解析默认标签
parseDefaultElement(ele, delegate);void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { //解析import标签 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } //解析alias标签 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } //解析bean标签 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } //解析beans标签,递归处理 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { doRegisterBeanDefinitions(ele); }}protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //1.委托BeanDefinitionPaserDelegate类进行元素解析,将BeanDefinition封装进BeanDefinitionHolder里面 //包含class、name、id属性 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { //2.若默认标签的子节点下有自定义属性,还需要再对自定义标签解析 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { //3.委托BeanDefinitionReaderUtils注册 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } //4.发出响应事件,通知想关心的监听事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); }}
2、解析BeanDefinition
BeanDefinition是一个接口,其抽象实现类为AbstractBeanDefinition,有三个子类,分别为RootBeanDefinition、ChildBeanDefinition和GenericBeanDefinition. BeanDefinition是配置文件bean元素在容器中的内部表现形式,和bean中属性一一对应.Spring通过BeanDefinition将配置文件中的bean配置信息转换为容器的内部表示,并将这些信息注册到BeanDefinitionRegistry中,它就是Spring配置信息的内存数据库,是一个Map,后续操作直接从该BeanDefinitionRegistry中读取配置信息.
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null);}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //解析id属性 String id = ele.getAttribute(ID_ATTRIBUTE); //解析name属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); //若nameAttr不为空,解析别名属性 Listaliases = new ArrayList (); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; //若没有指定id属性,使用别名的第一个代替 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } //进一步解析其他所有属性并封装到beanDefinition中 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null;}
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { String className = null; //解析className属性 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; //解析parent属性 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } //创建用于承载属性的GenericBeanDefinition,直接new的,并set传进去的参数 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //1.硬编码解析bean的各种属性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //2.解析description bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //3.解析元数据 parseMetaElements(ele, bd); //4.解析lookup-method属性,见附录1,实际要返回的bean是在配置文件里面配置的 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //5.解析replace-method属性,不但可以动态地替换返回实体的bean,而且还能动态地更改原有方法的逻辑 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //6.解析构造函数参数,property元素和qualifier元素 parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; }}
步骤1:硬编码解析bean的各种属性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,BeanDefinition containingBean, AbstractBeanDefinition bd) { //解析scope属性 if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Specify either 'scope' or 'singleton', not both", ele); } } //解析singleton属性 else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE); } else if (containingBean != null) { bd.setScope(containingBean.getScope()); } if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } //解析lazy-init属性,若不设置或者设置成其他字符都会设置为false String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //解析autowire属性 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE); bd.setDependencyCheck(getDependencyCheck(dependencyCheck)); if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); } String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); } if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } //解析init-method属性 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); if (!"".equals(initMethodName)) { bd.setInitMethodName(initMethodName); } } else { if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } } //解析destroy-method属性 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); if (!"".equals(destroyMethodName)) { bd.setDestroyMethodName(destroyMethodName); } } else { if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } } //解析factory-method属性 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); } //解析factory-bean属性 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); } return bd;}
步骤4、5:见附录1、2步骤6:解析构造函数参数
3、AbstractBeanDefinition
上述解析后的数据都放在AbstractBeanDefinition中.
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { private volatile Object beanClass; private String scope = SCOPE_DEFAULT; private boolean singleton = true; private boolean prototype = false; private boolean abstractFlag = false; private boolean lazyInit = false; private int autowireMode = AUTOWIRE_NO; private int dependencyCheck = DEPENDENCY_CHECK_NONE; private String[] dependsOn; //构造函数属性 private ConstructorArgumentValues constructorArgumentValues; //普通属性集合 private MutablePropertyValues propertyValues; //方法重写的持有者,记录lookup-method、replace-method元素 private MethodOverrides methodOverrides = new MethodOverrides(); private String factoryBeanName; private String factoryMethodName; private String initMethodName; private String destroyMethodName; //是否执行init-method和destroy-method private boolean enforceInitMethod = true; private boolean enforceDestroyMethod = true;}
4、注册BeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //解析BeanDefinition BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { //注册BeanDefinition到registry BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } //通知监听器解析及完成注册,当程序开发人员需要对注册BeanDefinition事件进行监听时可以通过注册监听器的方 //式并将处理逻辑写入监听器中,目前Spring中没有对此事件做任何逻辑处理 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); }}
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry){ String beanName = definitionHolder.getBeanName(); //使用beanName做唯一标识注册 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String aliase : aliases) { //使用别名做注册 registry.registerAlias(beanName, aliase); } }}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { if (beanDefinition instanceof AbstractBeanDefinition) { try { //做校验,抛异常部分已删除 ((AbstractBeanDefinition) beanDefinition).validate(); } } //beanDefinitionMap就是存放注册信息的全局变量,会存在并发访问的情况,加锁,它是ConcurrentHashMap //MapbeanDefinitionMap = new ConcurrentHashMap<>(64); synchronized (this.beanDefinitionMap) { Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); //处理已经注册beanName的情况 if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { //此处代码简略了,不允许覆盖则抛异常,允许覆盖则记录下日志 } } else { this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; } //真正进行注册 this.beanDefinitionMap.put(beanName, beanDefinition); } //清除缓存 resetBeanDefinition(beanName);}
5、解析alias标签
protected void processAliasRegistration(Element ele) { //获取beanName String name = ele.getAttribute(NAME_ATTRIBUTE); //获取别名alias String alias = ele.getAttribute(ALIAS_ATTRIBUTE); boolean valid = true; //之前有一些校验,删掉了 if (valid) { try { //注册 getReaderContext().getRegistry().registerAlias(name, alias); } getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); }}
6、解析import标签
protected void importBeanDefinitionResource(Element ele) { //解析resource属性,形如String location = ele.getAttribute(RESOURCE_ATTRIBUTE); //不存在直接返回 if (!StringUtils.hasText(location)) { getReaderContext().error("Resource location must not be empty", ele); return; } location = environment.resolveRequiredPlaceholders(location); Set actualResources = new LinkedHashSet (4); //判断是相对路径还是绝对路径 boolean absoluteLocation = false; try { absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); } if (absoluteLocation) { try { //是绝对路径,直接调用loadBeanDefinitions加载BeanDefinition,递归操作 int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); } }else { try { int importCount; //计算出绝对路径,进行loadBeanDefinitons Resource relativeResource = getReaderContext().getResource().createRelative(location); if (relativeResource.exists()) { importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = getReaderContext().getResource().getURL().toString(); importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); } } } Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]); getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));}
附录1:解析lookup-method
public class User { public void showMe(){ System.out.println("I am a User"); }}public class Teacher extends User{ @Override public void showMe() { System.out.println("I am a teacher"); }}public abstract class GetBeanTest { public void showMe(){ this.getBean().showMe(); } public abstract User getBean();}
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) { NodeList nl = beanEle.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)){ Element ele = (Element) node; //获取要修饰的方法 String methodName = ele.getAttribute(NAME_ATTRIBUTE); //获取配置返回的bean String beanRef = ele.getAttribute(BEAN_ELEMENT); LookupOverride override = new LookupOverride(methodName, beanRef); override.setSource(extractSource(ele)); overrides.addOverride(override); } }}
附录2:解析replace-method
public class TestChangeMethod { public void changeMe(){ System.out.println("changeMe"); }}public class TestMethodReplacer implements MethodReplacer{ public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { System.out.println("我替换了原有的方法"); return null; }}
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { NodeList nl = beanEle.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); //仅当在Spring默认bean的子元素下且为replace-method时才有效 if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { Element replacedMethodEle = (Element) node; //提取要替换的旧的方法,changeMe String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); //提取对应的新的替换方法,replacer String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); // Look for arg-type match elements. ListargTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); for (Element argTypeEle : argTypeEles) { //记录参数 String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); if (StringUtils.hasText(match)) { replaceOverride.addTypeIdentifier(match); } } replaceOverride.setSource(extractSource(replacedMethodEle)); overrides.addOverride(replaceOverride); } }}
感谢各位的阅读,以上就是"Spring实现解析默认标签的方法"的内容了,经过本文的学习后,相信大家对Spring实现解析默认标签的方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
属性
标签
方法
配置
元素
信息
监听
事件
别名
参数
路径
附录
处理
函数
就是
情况
数据
文件
步骤
监听器
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
数据库表的设计属于哪个阶段
对网络安全的未来展望
花都区软件开发培训班
中国十大计算机软件开发公司
数据库datet的创建方法
软件开发建模过程
网易邮箱登陆失败服务器
重庆高中网络技术知识点
软件开发人员的英语单词
nmap网络安全扫描
dhcp服务器配置动态ip地址
两微一端网络安全制度
服务器网线直连主机
数据库是软件科学么
网络技术包括后端开发吗
在数据库中表示实体的是
pytest如何断言数据库数据
软件开发挣外快
盐田区网络技术进出口价格走势
黄某对某超市服务器
兴化个性化网络技术诚信合作
业余软件开发著作权
万方数据库论文检索页如何下载
手机进入网站显示服务器
数据库显示附近有语法错误
数据库是软件科学么
编程和网络技术哪个有前途
工业和信息化局网络安全责任制
大学网络安全与防范措施
mssql主数据库服务器在哪里