当前位置: 首页 > news >正文

网站开发公司规章制度郑州网络推广培训

网站开发公司规章制度,郑州网络推广培训,在线建站系统,济宁seo优化公司Spring扩展点之Mybatis整合 单独使用MyBaitis模拟整合MyBatis到Spring 单独使用MyBaitis 通过配置文件生成sqlSessionFactory,用sqlSessionFactory开启session。通过session获取到mapper执行对应的sql。 InputStream inputStream Resources.getResourceAsStream(…

Spring扩展点之Mybatis整合

  • 单独使用MyBaitis
  • 模拟整合MyBatis到Spring

单独使用MyBaitis

通过配置文件生成sqlSessionFactory,用sqlSessionFactory开启session。通过session获取到mapper执行对应的sql。

InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
String result = userMapper.selectById();sqlSession.commit();
sqlSession.flushStatements();
sqlSession.close();

模拟整合MyBatis到Spring

在Spring中我们可以通过如下方式使用mapper。通过分析我们知道userMapper是MyBatis生成的代理对象。但是在下面代码中的mapper并不是代理对象,并且运行还会报错,因为接口不会扫描成为bean。

public interface UserMapper {@Select("select 'user'")String selectById();
}@Component
public class UserService {@Autowiredprivate UserMapper userMapper;public void test() {System.out.println(userMapper.selectById());}
}@ComponentScan("org.example")
public class Application {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);UserService userService = context.getBean(UserService.class);userService.test();}
}

我们可以通过FactoryBean接口模拟代理对象的实现。

@Component
public class XianNuFactoryBean implements FactoryBean {public Object getObject() throws Exception {Object proxyInstance = Proxy.newProxyInstance(XianNuFactoryBean.class.getClassLoader(), new Class[]{UserMapper.class}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 处理代理逻辑return null;}});return proxyInstance;}public Class<?> getObjectType() {return UserMapper.class;}
}

添加上述代码后,代码可以正常运行,可以userMapper可以注入成功。但是还有一个问题,这里的代理对象是写死的,我们不能每个mapper都写一个工厂bean吧。此时,我们可以想到利用spring的BeanDefinition把工厂bean注册到容器中。

public class XianNuFactoryBean implements FactoryBean {public Class clazz;public XianNuFactoryBean(Class clazz) {this.clazz = clazz;}public Object getObject() throws Exception {Object proxyInstance = Proxy.newProxyInstance(XianNuFactoryBean.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 处理代理逻辑return null;}});return proxyInstance;}public Class<?> getObjectType() {return clazz;}
}

工厂bean进行改造,增加构造器指定bean类型。

@Component
public class XianNuBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(XianNuFactoryBean.class);AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserMapper.class);beanDefinitionRegistry.registerBeanDefinition("userMapper", beanDefinition);}public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {//...}
}

接下来就顺利成章了,我们想要扫描用户所有的mapper然后自动注册到Spring容器中。利用@Import注解配合ImportBeanDefinitionRegistrar。@Import可以获取到所有类的元数据信息,如其他注解的扫描路径。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface XianNuMapperScan {String value();
}@ComponentScan("org.example")
@XianNuMapperScan("org.example.mapper")
@Import(XianNuImportBeanDefinitionRegistrar.class)
public class Application {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);UserService userService = context.getBean(UserService.class);userService.test();}
}public class XianNuImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {// 解析扫描路径Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(XianNuMapperScan.class.getName());String path = (String) annotationAttributes.get("value");System.out.println(path);// 扫描路径下的bean?BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(XianNuFactoryBean.class);AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserMapper.class);beanDefinitionRegistry.registerBeanDefinition("userMapper", beanDefinition);}
}

得到扫描路径后需要扫描路径下的类,我们可以利用spring的扫描器来处理。由于Spring本身的扫描器不处理接口,因此我们需要重新 isCandidateComponent(AnnotatedBeanDefinition beanDefinition)方法让他处理接口。此外扫描时还有一个exclude/includeFilters的判断,Spring默认添加component注解进行扫描,因此我们可以在mapper上加注解就能扫描到,此外还有一个方法就是在扫描器添加includeFilter。

public class XianNuBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {public XianNuBeanDefinitionScanner(BeanDefinitionRegistry registry) {super(registry);}@Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {return beanDefinition.getMetadata().isInterface();}
}public class XianNuImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {// 解析扫描路径Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(XianNuMapperScan.class.getName());String path = (String) annotationAttributes.get("value");System.out.println(path);// 扫描路径下的beanXianNuBeanDefinitionScanner scanner = new XianNuBeanDefinitionScanner(beanDefinitionRegistry);scanner.addIncludeFilter(new TypeFilter() {public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {return true;}});scanner.scan(path);//        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(XianNuFactoryBean.class);
//        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
//        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserMapper.class);
//        beanDefinitionRegistry.registerBeanDefinition("userMapper", beanDefinition);}

此时扫描出的mapper的BeanDefinition的class是它本身,并不是代理对象,因此还需要对beanDefinition做一些处理。重写scanner父类的doScan方法。

public class XianNuBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {public XianNuBeanDefinitionScanner(BeanDefinitionRegistry registry) {super(registry);}// 修改BeanDefinition的class为工厂类@Overrideprotected Set<BeanDefinitionHolder> doScan(String... basePackages) {Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition.getBeanClassName());beanDefinition.setBeanClassName(XianNuFactoryBean.class.getName());}return beanDefinitionHolders;}// 让扫描器扫描接口@Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {return beanDefinition.getMetadata().isInterface();}

此时还有一个问题就,就是mapper的代理逻辑是我们自己写的,不是用的MyBatis的。我们看mybatis的原始用法发现,mapper可以通过sqlSessionFactory得到,而sqlSessionFactory是通过配置文件得到。

public class XianNuFactoryBean implements FactoryBean {public Class clazz;@Autowiredprivate SqlSessionFactory sqlSessionFactory;public XianNuFactoryBean(Class clazz) {this.clazz = clazz;}public Object getObject() throws Exception {
//        Object proxyInstance = Proxy.newProxyInstance(XianNuFactoryBean.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                // 处理代理逻辑
//                System.out.println(method.getName());
//                return null;
//            }
//        });
//        return proxyInstance;sqlSessionFactory.getConfiguration().addMapper(clazz);return sqlSessionFactory.openSession().getMapper(clazz);}public Class<?> getObjectType() {return clazz;}
}@ComponentScan("org.example")
@XianNuMapperScan("org.example.mapper")
@Import(XianNuImportBeanDefinitionRegistrar.class)
@Configuration
public class AppConfig {@Beanpublic SqlSessionFactory getSqlSessionFactory() throws IOException {InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);return sqlSessionFactory;}
}

至此模拟整合完成。

http://www.yayakq.cn/news/482998/

相关文章:

  • 温州集团网站建设公司百度收录入口提交查询
  • 常州做网站公司排名有哪些网站做生鲜到家
  • 开发一套网站系统 多少钱城乡建设学校网站
  • wordpress影视站主题上海seo外包
  • 厦门安能建设品牌网站建设ui设计工资
  • 企业网站开发效果北京网站开发哪家好
  • 用模板做网站会被盗吗wordpress 模版安装教程
  • 优惠网站怎么做网站建设选哪个好
  • seo做的好的网站做直播网站需要哪些技术
  • wordpress编辑网站no7wordpress
  • 竹子建站怎么赚钱菠萝蜜一区二免费进入
  • 大学生网站作业桂林欣梦网络招聘
  • 网站建设好学么广州网页搜索排名提升
  • 如何在淘宝上接单网站建设wordpress调用新版媒体库
  • cms 类网站网站标准规范建设
  • 做网站还需要服务器吗企业网站建站公司郑州
  • 怎么做百度快照让网站排前面安卓手机app下载
  • 贵州省城乡和住房建设厅网站长沙公司建
  • 网站背景素材百度资源搜索平台
  • 淄博外贸网站建设公司抖音seo工具
  • 学校营销型网站安卓app开发技术
  • 一个空间2个网站成品网站怎么新建网页
  • 广州网站建设 app 小程序做视频大赛推广的网站
  • 二手房中介网站模板股权分配方案创业初期
  • 连接国外网站做端口映射去年做哪些网站能致富
  • 八年级信技做网站html如果制作一个内容多的网站
  • 杭州网站 建设上海网络推广优化公司
  • 网站logo模板抖音热门搜索关键词
  • 网站更改公司需要重新备案吗织梦后台怎么做网站地图
  • 营销网站建设的步骤过程wordpress文章所有图片大小