您的位置:首页 > 文旅 > 旅游 > 国企招聘网最新招聘2023_网站的网络营销方案_谷歌排名规则_百度的链接

国企招聘网最新招聘2023_网站的网络营销方案_谷歌排名规则_百度的链接

2024/12/24 2:06:13 来源:https://blog.csdn.net/m0_75113406/article/details/144583325  浏览:    关键词:国企招聘网最新招聘2023_网站的网络营销方案_谷歌排名规则_百度的链接
国企招聘网最新招聘2023_网站的网络营销方案_谷歌排名规则_百度的链接

Spring xml方式整合第三方框架

xml整合第三方框架有两种整合方案:

​ · 不需要自定义名空间,不需要使用Spring的配置文件配置第三方框架本身内容,例如:MyBatis;

​ · 需要引入第三方框架命名空间,需要使用Spring的配置文件配置第三方框架本身内容,例如:Dubbo。

Spring整合MyBatis,之前已经在Spring中简单的配置了SqlSessionFactory,但是这不是正规的整合方式,

MyBatis提供了mybatis-spring.jar专门用于两大框架的整合。

Spring整合MyBatis的步骤如下:

​ · 导入MyBatis整合Spring的相关坐标;(请见资料中的pom.xml)

​ · 编写Mapper和Mapper.xml;

​ · 配置SqlSessionFactoryBean和MapperScannerConfigurer;

​ · 编写测试代码

配置SqlSessionFactoryBean和MapperScannerConfigurer:

<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="jdbc:mysql://localhost:3306/mybatis"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>
<!--配置SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置Mapper包扫描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.zjy.dao"></property>
</bean>

编写Mapper和Mapper.xml

public interface UserMapper {List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zjy.dao.UserMapper"><select id="findAll" resultType="com.zjy.pojo.User">select * from tb_user</select>
</mapper>

编写测试代码

ClassPathxmlApplicationContext applicationContext =new ClassPathxmlApplicationContext("applicationContext.xml");
UserMapper userMapper = applicationContext.getBean(UserMapper.class);
List<User> all = userMapper.findAll();
System.out.println(all);

Spring整合MyBatis的原理剖析

整合包里提供了一个SqlSessionFactoryBean和一个扫描Mapper的配置对象,SqlSessionFactoryBean一旦被实例化,就开始扫描Mapper并通过动态代理产生Mapper的实现类存储到Spring容器中。相关的有如下四个类:

​ · SqlSessionFactoryBean:需要进行配置,用于提供SqlSessionFactory;

​ · MapperScannerConfigurer:需要进行配置,用于扫描指定mapper注册BeanDefinition;

​ · MapperFactoryBean:Mapper的FactoryBean,获得指定Mapper时调用getObject方法;

​ · ClassPathMapperScanner:definition.setAutowireMode(2) 修改了自动注入状态,所以MapperFactoryBean中的setSqlSessionFactory会自动注入进去。

配置SqlSessionFactoryBean作用是向容器中提供SqlSessionFactory,SqlSessionFactoryBean实现了FactoryBean和InitializingBean两个接口,所以会自动执行getObject() 和afterPropertiesSet()方法

SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean{public void afterPropertiesSet() throws Exception {//创建SqlSessionFactory对象this.sqlSessionFactory = this.buildSqlSessionFactory();}public SqlSessionFactory getObject() throws Exception {return this.sqlSessionFactory;}
}

配置MapperScannerConfigurer作用是扫描Mapper,向容器中注册Mapper对应的MapperFactoryBean,MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor和InitializingBean两个接口,会在postProcessBeanDefinitionRegistry方法中向容器中注册MapperFactoryBean

class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean{public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));}
}
class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {public Set<BeanDefinitionHolder> doScan(String... basePackages) {Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);if (beanDefinitions.isEmpty()) {} else {this.processBeanDefinitions(beanDefinitions);}}private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {//设置Mapper的beanClass是org.mybatis.spring.mapper.MapperFactoryBeandefinition.setBeanClass(this.mapperFactoryBeanClass);definition.setAutowireMode(2); //设置MapperBeanFactory 进行自动注入}
}

autowireMode取值:1是根据名称自动装配,2是根据类型自动装配

class ClassPathBeanDefinitionScanner{public int scan(String... basePackages) {this.doScan(basePackages);}protected Set<BeanDefinitionHolder> doScan(String... basePackages) {//将扫描到的类注册到beanDefinitionMap中,此时beanClass是当前类全限定名this.registerBeanDefinition(definitionHolder, this.registry);return beanDefinitions;}
}
UserMapper userMapper = applicationContext.getBean(UserMapper.class);
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {public MapperFactoryBean(Class<T> mapperInterface) {this.mapperInterface = mapperInterface;}public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory);}public T getObject() throws Exception {return this.getSqlSession().getMapper(this.mapperInterface);}
}

Spring 整合其他组件

Spring 整合其他组件时就不像MyBatis这么简单了,例如Dubbo框架在于Spring进行整合时,要使用Dubbo提供的命名空间的扩展方式,自定义了一些Dubbo的标签

<?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:dubbo="http://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><!--配置应用名称--><dubbo:application name="dubbo1-consumer"/><!--配置注册中心地址--><dubbo:registry address="zookeeper://localhost:2181"/><!--扫描dubbo的注解--><dubbo:annotation package="com.itheima.controller"/><!--消费者配置--><dubbo:consumer check="false" timeout="1000" retries="0"/>
</beans>

引入context命名空间,在使用context命名空间的标签

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:jdbc.properties" /><beans>

原理剖析解析过程,只能从源头ClassPathXmlApplicationContext入手,经历复杂的源码追踪,找到如下两个点:

1)在创建DefaultNamespaceHandlerResolver时,为处理器映射地址handlerMappingsLocation属性赋值,并加载命名空间处理器到Map<String, Object> handlerMappings 中去

this.handlerMappingsLocation = "META-INF/spring.handlers";

在这里插入图片描述

第一点完成后,Map集合handlerMappings就被填充了很多XxxNamespaceHandler,继续往下追代码

2)在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法中,发现如下逻辑:

//如果是默认命名空间
if (delegate.isDefaultNamespace(ele)) {this.parseDefaultElement(ele, delegate);//否则是自定义命名空间
} else {delegate.parseCustomElement(ele);
}

如果是默认命名空间,则执行parseDefaultElement方法

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, "import")) {this.importBeanDefinitionResource(ele);} else if (delegate.nodeNameEquals(ele, "alias")) {this.processAliasRegistration(ele);} else if (delegate.nodeNameEquals(ele, "bean")) {this.processBeanDefinition(ele, delegate);} else if (delegate.nodeNameEquals(ele, "beans")) {this.doRegisterBeanDefinitions(ele);}
}

如果是自定义命名空间,则执行parseCustomElement方法

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {//解析命名空间String namespaceUri = this.getNamespaceURI(ele);//获得命名空间解析器NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//解析执行的标签return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

在执行resovle方法时,就是从Map<String, Object> handlerMappings中根据命名空间名称获得对应的处理器对象,此处是ContextNamespaceHandler,最终执行NamespaceHandler的parse方法

ContextNamespaceHandler源码如下,间接实现了NamespaceHandler接口,初始化方法init会被自动调用。由于context命名空间下有多个标签,所以每个标签又单独注册了对应的解析器,注册到了其父类NamespaceHandlerSupport的Map<String, BeanDefinitionParser> parsers中去了

public class ContextNamespaceHandler extends NamespaceHandlerSupport {public ContextNamespaceHandler() {}public void init() {this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());this.registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());this.registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());this.registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());this.registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());this.registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());this.registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());}
}

流程总结

将自定义标签的约束 与 物理约束文件与网络约束名称的约束 以键值对形式存储到一个spring.schemas文件里,该文件存储在类加载路径的 META-INF里,Spring会自动加载到;

将自定义命名空间的名称与自定义命名空间的处理器映射关系 以键值对形式存在到一个叫spring.handlers文件里,该文件存储在类加载路径的 META-INF里,Spring会自动加载到;

准备好NamespaceHandler,如果命名空间只有一个标签,那么直接在parse方法中进行解析即可,一般解析结果就是注册该标签对应的BeanDefinition。如果命名空间里有多个标签,那么可以在init方法中为每个标签都注册一个BeanDefinitionParser,在执行NamespaceHandler的parse方法时在分流给不同的BeanDefinitionParser进行解析(重写doParse方法即可)。

进行某一个框架与Spring的集成开发

设想自己是一名架构师,进行某一个框架与Spring的集成开发,效果是通过一个指示标签,向Spring容器中自动注入一个BeanPostProcessor

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/xmlSchema-instance"xmlns:xiaozhang="http://www.zjy.com/xiaozhang"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.zjy.com/xiaozhang http://www.itheima.com/haohao/haohao-annotation.xsd"><xiaozhang:annotation-driven/>
</beans>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com