转自;https://www.cnblogs.com/sonofelice/p/4980161.html

1.

最近在学习spring和ibatis框架。

以前在天猫实习时做过的一个小项目用到的mybatis,在其使用过程中,不加思索的用了比较原始的一种持久化方式:

在一个包中写一个DAO的接口,在另一个包里面写DAO的实现,使用sqlMapClient来从***-sql.xml中读取相应的sql。

 1 public interface IBaseDaoiBatis {
 2      Object get(String statementName);
 3 }
 4 public class BaseDaoiBatis implements IBaseDaoiBatis {
 5  public Object get(String statementName) {
 6         return getSqlMapClientTemplate().queryForObject(statementName);
 7     }
 8 }
 9 //对应的mybatis配置文件里面的sql:
10 <sqlMap>
11     <typeAlias alias="sonarBean" type="com.**--**.SonarScanDataDisplayBean" />
12     <select id="getSonarScanData" parameterClass="java.lang.Integer" resultClass="java.lang.String">
13         <![CDATA[
14             SELECT  name FROM mm_test  where id=#id#;
15         ]]>
16     </select>
17 </sqlMap>

最近搭建了一个spring+ibatis的项目,发现了一种新的持久化方式:

只写一个dao的接口,在接口的方法中直接注解上用到的sql语句,觉得蛮巧妙的。借来用一下。注意,接口上方多了一个@Mapper注解。而每个方法上都是@Select() 注解,值为对应的sql。

1 @Mapper
2 public interface TestDao {
3     @Select("select id, name, name_pinyin from mm_test; ")
4     List<MmTest> selectAll();
5
6     @Insert("insert into mm_test(id, name) values(#{id}, #{name})")
7     public void insertUser(MmTest mmtTestS);
8 }

那么这个@Mapper注解究竟是个什么东西,是怎么起到注解的作用的?ibatis是怎么来识别这种注解的呢?对我这个java小白来说,注解,是spring特有的东西嘛?自学java的时候好像很少接触注解啊。不过竟然有java.lang.annotation 这个包,这到底是怎么回事?

那我们先来看一下Mapper这个自定义注解的定义:

 1 import org.springframework.stereotype.Component;
 2
 3 import java.lang.annotation.*;
 4 @Target({ ElementType.TYPE })
 5 @Retention(RetentionPolicy.RUNTIME)
 6 @Documented
 7 @Component
 8 public @interface Mapper {
 9     String value() default "";
10 }

关于自定义注解:(查的别人的博客:http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html)博客里面写的非常详细,并且注解的使用机制很容易理解。

拿上述的@Mapper来说,Retention选择的是RUNTIME策略,就是运行时注入。那么要在运行时获得注入的值,必然要用到java的反射机制。通过反射,拿到一个类运行时的方法变量等,来进行一系列的操作。

那我要考虑的下一个问题是,我定义的@Mapper,在我的工程里面是怎么识别的呢?

来看一下我spring的配置文件中关于mybatis的配置

 1 <!--mybatis-->
 2     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 3         <property name="dataSource" ref="dataSource" />
 4         <property name="configLocation">
 5             <value>classpath:myBatis/mapper.xml</value>
 6         </property>
 7     </bean>
 8     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
 9         <property name="basePackage" value="com.**.**.**.dao" />
10         <property name="annotationClass" value="com.nuomi.crm.annotation.Mapper"/>
11         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
12     </bean>

在org.mybatis.spring.mapper.MapperScannerConfigurer这个类里面,应该是会去扫描我自定义的com.nuomi.crm.annotation.Mapper这个类的。

 1 <configuration>
 2     <settings>
 3         <!-- 将下划线字段名称映射为驼峰变量  -->
 4         <setting name="mapUnderscoreToCamelCase" value="true" />
 5         <!-- 进制mybatis进行延迟加载 -->
 6         <setting name="lazyLoadingEnabled" value="false"/>
 7     </settings>
 8     <mappers>
 9     </mappers>
10 </configuration>

在我的mapper.xml里面只需要进行这一简单的配置就可以了(配置的含义后续补充)

接下来看一下mybatis自带的这个MapperScannerConfigurer究竟怎么实现的,来使用我这个自定义的注解@Mapper呢。

 1 public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
 2 private Class<? extends Annotation> annotationClass;
 3   public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
 4     this.annotationClass = annotationClass;
 5   }/**
 6    * {@inheritDoc}
 7    *
 8    * @since 1.0.2
 9    */
10   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
11     if (this.processPropertyPlaceHolders) {
12       processPropertyPlaceHolders();
13     }
14
15     ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
16     scanner.setAddToConfig(this.addToConfig);
17     scanner.setAnnotationClass(this.annotationClass);
18     scanner.setMarkerInterface(this.markerInterface);
19     scanner.setSqlSessionFactory(this.sqlSessionFactory);
20     scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
21     scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
22     scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
23     scanner.setResourceLoader(this.applicationContext);
24     scanner.setBeanNameGenerator(this.nameGenerator);
25     scanner.registerFilters();
26     scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
27   }
28
29   /*
30    * BeanDefinitionRegistries are called early in application startup, before
31    * BeanFactoryPostProcessors. This means that PropertyResourceConfigurers will not have been
32    * loaded and any property substitution of this class' properties will fail. To avoid this, find
33    * any PropertyResourceConfigurers defined in the context and run them on this class' bean
34    * definition. Then update the values.
35    */
36   private void processPropertyPlaceHolders() {
37     Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
38
39     if (!prcs.isEmpty() && applicationContext instanceof GenericApplicationContext) {
40       BeanDefinition mapperScannerBean = ((GenericApplicationContext) applicationContext)
41           .getBeanFactory().getBeanDefinition(beanName);
42
43       // PropertyResourceConfigurer does not expose any methods to explicitly perform
44       // property placeholder substitution. Instead, create a BeanFactory that just
45       // contains this mapper scanner and post process the factory.
46       DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
47       factory.registerBeanDefinition(beanName, mapperScannerBean);
48
49       for (PropertyResourceConfigurer prc : prcs.values()) {
50         prc.postProcessBeanFactory(factory);
51       }
52
53       PropertyValues values = mapperScannerBean.getPropertyValues();
54
55       this.basePackage = updatePropertyValue("basePackage", values);
56       this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);
57       this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);
58     }
59   }
60
61 }

上面只是截取的关于annotation的代码片段.

scanner.setAnnotationClass(this.annotationClass);这里会去扫描配置的那个注解类。

mybatis的内部实现会使用java反射机制来在运行时去解析相应的sql。

(上面写的还不是很完全,后续补充。)

转载于:https://www.cnblogs.com/sharpest/p/6097682.html

mybatis对java自定义注解的使用——入门篇相关推荐

  1. java 自定义注解_两步实现Java自定义注解

    什么是注解? 注解就是为容器提供元数据,例如@Controller 注解则是标记了该Bean需要交给Spring容器进行管理. 那么我们怎么去实现自个的注解,也就是自定义注解呢? 一.自定义一个注解( ...

  2. java自定义注解实现前后台参数校验

    其实是可以通过@Constraint来限定自定义注解的方法. @Constraint(validatedBy = xxxx.class) 下面是我做的 java自定义注解实现前后台参数校验 的代码示例 ...

  3. java自定义注解类

    一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...

  4. java 自定义注解实现不同对象之间的拷贝(支持大小写、驼峰转换)

    java 自定义注解实现不同对象之间的拷贝(支持大小写.驼峰转换) 1.需求 要实现两个属性名称完全不同的对象之间的拷贝.具体如下 原对象 /*** 原实体*/ @Data public class ...

  5. Java 自定义注解及使用场景

    文章目录 1 什么是注解(Annotation) 2 元注解 2.1 @Target 2.2 @Retention 2.3 @Repeatable 2.4 @Inherited 示例1 反射获取注解 ...

  6. java中注解动态传参_Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)...

    Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)java 前言:因为前段时间忙于写接口,在接口中须要作不少的参数校验,本着简洁.高效的原则,便写了这个小工具供本身使 ...

  7. Java 自定义注解简单使用

    Java 自定义注解简单使用 文章目录 Java 自定义注解简单使用 第一步:在 pom.xml 下引入反射框架 第二步:自定义注解 第三步:写两个测试实体类 第四步:写个工具类扫描被注解的类(核心) ...

  8. springboot项目中自定义注解的使用总结、java自定义注解实战(常用注解DEMO)

    初学spring的时候使用注解总觉得使用注解很神奇,加一个注解就能实现想要的功能,很好奇,也想自己根据需要写一些自己实现的自定义注解.问题来了,自定义注解到底是什么?肯定会有人和我一样有这个疑惑,我根 ...

  9. java 自定义注解 教程_Java注解教程及自定义注解

    Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许 ...

最新文章

  1. error 系统错误 错误码10007_为什么阿里巴巴禁止工程师直接使用日志系统( Log4j 、Logback )中的 API...
  2. git cherry-pick 分支转移教程
  3. Python之基础知识
  4. Java中常见的异常
  5. Fabric--使用多通道
  6. Linux C:文件描述符、IO重定向、恢复标准输入输出
  7. linux下使用python3_Linux上python3的安装和使用
  8. Java黑皮书课后题第9章:9.2(Stock类)遵照9.2节中Cirlce类的例子,设计一个名为Stock的类
  9. Code Review的重要性
  10. new malloc
  11. C++_public、private、protected权限介绍
  12. 怎么进入机顶盒linux系统,如何在机顶盒中刷入原生的Debian系统
  13. 域控激活计算机用户,Windows2008AD 域控安装(示例代码)
  14. J2ME学习过程中的一点心得整理(参考:java手机/PDA程序设计入门 王森)
  15. Java 正则校验手机号 工具类
  16. 2021第七届美亚杯中国电子数据取证大赛详解write up
  17. JMeter 系列 —— BeanShell 取样器
  18. 滴滴出行数据应用平台建设实践
  19. 华为云IoT智慧物流案例11 | 华为云FOTA升级广和通L610模组
  20. java抽组件_GitHub - ysc/HtmlExtractor: HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件。...

热门文章

  1. 七七计算机论文网,qepipnu
  2. java写入数组_如何在Java中将数组写入outputStream
  3. oracle中的自带函数,求完整的ORACLE自带函数文档
  4. 射灯安装方法图解_家居射灯怎么选?第三代宜美SMD射灯给你正解
  5. 河南理工大学c语言报告封面,河南理工大学图书信息管理系统设计_纯c语言课程设计.doc...
  6. 【Java基础篇】Unicode、进制转换
  7. 在 Windows 命令提示符下启动 MySQL:net start mysql 发生系统错误 5。 拒绝访问。解决方式小结
  8. Java中List、Map、Set三个接口,存取元素时,各有什么特点?
  9. 你的main函数规范吗?
  10. php访问网页post获取源码,第一次抓别人网站数据,用postman直接请求可以获取到返回数据,通过代码的方式就一直报错,php...