• Java 注解


    一、注解的概念

    注解(Annotation),也叫元数据(Metadata),是 Java5 的新特性,JDK5引入了 Metadata 很容易的就能够调用 Annotations。注解与类、接口、枚举在同一个层次,并可以应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中,用来对这些元素进行说明注释。

    二、注解的语法与定义形式

    1. 以 @interface 关键字定义
    2. 注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
    3. 成员赋值是通过 @Annotation(name=value) 的形式。
    4. 注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
    @Retention(value = RetentionPolicy.RUNTIME)
    @Target(value = { ElementType.ANNOTATION_TYPE } )
    public @interface Target {
        ElementType[] value();
    }
    

    三、注解的分类

    3.1 元注解

    meta-annotation。

    负责注解其他注解的注解。JDK 1.5 及以后版本定义了 4 个标准的元注解类型:

    1. @Documented

      标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如 javadoc 此类的工具文档化。

      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.ANNOTATION_TYPE)
      public @interface Documented {
      }
    2. @Inherited

      标记注解,允许子类继承父类的注解

      @Inherited
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.ANNOTATION_TYPE)
      public @interface Inherited {
      }
    3. @Retention

      指注解被保留的时间长短,标明注解的生命周期。

      public enum RetentionPolicy {
          /**
      * 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃.
      * 这意味着:Annotation仅存在于编译器处理期间,编译器处理完之后,该Annotation就没用了
      */
      SOURCE,
      /**
      * 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期.
      */
      CLASS,
      /**
      * 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,
      * 保存到class对象中,可以通过反射来获取
      */
      RUNTIME
      }
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.ANNOTATION_TYPE)
      public @interface Retention {
      RetentionPolicy value();
      }
    4. @Target

      标明注解的修饰目标。

      // ElementType取值
      public enum ElementType {
      /* 类、接口(包括注解类型)或枚举 */
      TYPE,
      /* field属性,也包括enum常量使用的注解 */
      FIELD,
      /* 方法 */
      METHOD,
      /* 参数 */
      PARAMETER,
      /* 构造函数 */
      CONSTRUCTOR,
      /* 局部变量 */
      LOCAL_VARIABLE,
      /* 注解上使用的元注解 */
      ANNOTATION_TYPE,
      /* 包 */
      PACKAGE
      }

    3.2 XStream

    1. @XStreamAlias()

      给类取别名。等同于 stream.alias("student", Student.class);

      @XStreamAlias("student")  // define class level alias
      class Student { 
      }

      给属性取别名。等同于 stream.aliasField("name", Student.class, "studentName");

      class Student {
          @XStreamAlias("name")   // define field level alias
      @XStreamAsAttribute // define field as attribute
      private String studentName;
      }
    2. @XStreamImplicit

      隐藏集合类节点。等同于 stream.addImplicitCollection(Student.class, "notes");

      class Student {
          @XStreamImplicit  // define list as an implicit collection
      private List<Note> notes = new ArrayList<Note>();
      }

    3.3 Hibernate

    1. @Entity

      映射实体类。将一个类声明为一个实体 bean,映射到指定的数据库表。

      必须使用。

      @Entity(name = "tableName")
      public class Student {
      }
      • name - 可选,对应数据库中的一个表。若表名与实体类名相同,则可以省略。
    2. @Table

      映射数据库表。通常和 @Entity 配合使用,只能标注在实体的 class 定义上,表示实体对应的数据库表的信息。

      可选使用。

      @Entity(name = "tableName")
      @Table(name = "t_student", catalog = "", schema = "")
      public class Student {
      }
      • name - 可选,表示表的名称,默认的表名和实体名称一致,只有在不一致的情况下才需要指定表名
      • catalog - 可选,表示 Catalog 名称,默认为 Catalog("")
      • schema - 可选 , 表示 Schema 名称 , 默认为Schema("")
    3. @Id

      映射生成主键。定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键,置于 getXxx() 前。

    4. @GeneratedValue

      定义主键生成策略

    5. @SequenceGenerator

      声明了一个数据库序列

    6. @Version

      定义乐观锁

    7. @Basic

      声明属性的存取策略

    8. @Column

      映射表的列

    9. @Transient

      定义暂态属性

      Hibernate的注解方法的使用

    3.4 校验

    1. @Valid

      用于验证注解是否符合要求,直接加在变量之前,在变量中添加验证信息的要求,当不符合要求时就会在方法中返回 message 的错误提示信息。

      @RestController
      @RequestMapping("/user")
      public class UserController {
      @PostMapping
      public User create (@Valid @RequestBody User user) {
      user.setId("1");
      return user;
      }
      }
    2. @NotBlank

      public class User {
          private String id;  
      @NotBlank(message = "密码不能为空")
      private String password;
      }

      当密码为空时,@Valid 验证失败,会将 message 字段的信息返回。

      其他验证信息的要求:

      限制 说明
      @Null 限制只能为 null
      @NotNull 限制必须不为 null
      @AssertFalse 限制必须为 false
      @AssertTrue 限制必须为 true
      @DecimalMax(value) 限制必须为一个不大于指定值的数字
      @DecimalMin(value) 限制必须为一个不小于指定值的数字
      @Digits(integer, fraction) 限制必须为一个小数,且整数部分的位数不能超过 integer,小数部分的位数不能超过fraction
      @Future 限制必须是一个将来的日期
      @Past 限制必须是一个过去的日期
      @Max(value) 限制必须为一个不大于指定值的数字
      @Min(value) 限制必须为一个不小于指定值的数字
      @Pattern(value) 限制必须符合指定的正则表达式
      @Size(max,min) 限制字符长度必须在 min 到 max 之间
      @Past 验证注解的元素值(日期类型)比当前时间早
      @NotEmpty 验证注解的元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0)
      @NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于 @NotEmpty,@NotBlank 只应用于字符串且在比较时会去除字符串的空格
      @Email 验证注解的元素值是 Email,也可以通过正则表达式和 flag 指定自定义的 email 格式
    3. 自定义验证信息

      @Constraint(validatedBy = {MyConstraintValidator.class})
      @Target({ELementtype.METHOD, ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface MyConstraint {
      String message();
      Class<?>[] groups() default {};
      Class<? extends Payload>[] payload() default {};
      }

      校验器:

      public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Object> {
          @Autowired
      private UserService userService;
      @Override
      public void initialie(@MyConstraint constarintAnnotation) {
      System.out.println("my validator init");
      }
      @Override
      public boolean isValid(Object value, ConstraintValidatorContext context) {
      userService.getUserByUsername("seina");
      System.out.println("valid");
      return false;
      }
      }

    3.5 Spring

    1. @Controller

      控制器(注入服务)。用于标注控制层,相当于 struts 中的 action 层。

    2. @Service

      服务(注入 dao)。用于标注服务层,主要用来进行业务的逻辑处理。

    3. @Repository

      实现 dao 访问。用于标注数据访问层,也可以说用于标注数据访问组件,即 DAO 组件。

    4. @Component

      把普通 pojo 实例化到 spring 容器中,相当于配置文件中的 <bean id="" class=""/>。泛指各种组件,就是说当类不属于各种归类的时候(不属于 @Controller、@Service等时),就可以使用 @Component 来标注这个类。

    5. @Configuration

      标识类可以使用 Spring IoC 容器作为 bean 定义的来源,配合 @Bean 使用。使用这两个注解就可以创建一个简单的 spring 配置类,可以用来替代相应的 xml 配置文件。

      <beans> 
          <bean id = "car" class="com.test.Car"> 
      <property name="wheel" ref = "wheel"></property>
      </bean>
      <bean id = "wheel" class="com.test.Wheel"></bean>
      </beans>
      @Configuration 
      public class Conf { 
      @Bean
      public Car car() {
      Car car = new Car();
      car.setWheel(wheel());
      return car;
      }
      @Bean
      public Wheel wheel() {
      return new Wheel();
      }
      }
    6. @Bean

      告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean。

    7. @EnableAspectJAutoProxy

      开启 AOP。

      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Import(AspectJAutoProxyRegistrar.class)
      public @interface EnableAspectJAutoProxy {
      /**
      * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
      * to standard Java interface-based proxies. The default is {@code false}.
      */
      boolean proxyTargetClass() default false;
      /**
      * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
      * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
      * Off by default, i.e. no guarantees that {@code AopContext} access will work.
      * @since 4.3.1
      */
      boolean exposeProxy() default false;
      }

      proxyTargetClass 控制 aop 的具体实现方式。为 true 的话使用 cglib,为 false 的话使用 java 的 Proxy。

      exposeProxy 控制代理的暴露方式,解决内部调用不能使用代理的场景。

      spring @EnableAspectJAutoProxy背后的那些事(spring AOP源码赏析)

    8. @EnableTransactionManagement

      开启 spring 事务管理。

    9. @EnableCaching

      开启 spring 缓存。

    10. @EnableWebMvc

      开启 webMvc。

    11. @Resource 与 @Autowired 用法区别

      共同点:

      • @Resource 和 @Autowired 都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。

      不同点:

      • @Resource 是 Java 的注解,@Resource 有两个属性是比较重要的,name 和 type;Spring 将 @Resource 注解的 name 属性解析为 bean的名字,而 type 属性则解析为 bean 的类型。如果一个 bean 的name 和另外一个 bean 的 property 相同,就自动装配;如果一个bean 的数据类型和另外一个 bean 的 property 属性的数据类型兼容,就自动装配。
      • @Autowired 是 spring 的注解,是 spring2.5 版本引入的,@Autowired 只根据 type 进行注入,不会去匹配 name。如果涉及到 type 无法辨别注入对象时,那需要依赖 @Qualifier 或 @Primary 注解一起来修饰。

      @Resource与@Autowired用法区别

    3.6 SpringBoot

    1. @ServletComponentScan

      在 SpringBootApplication 上使用 @ServletComponentScan 注解后,Servlet、Filter、Listener可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

      @SpringBootApplication
      @ServletComponentScan
      public class Application {
      public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
      }
      }
      @WebServlet(name="TestServlet", urlPatterns="/test")
      public class TestServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
      }
      }
    2. @ComponentScan

      Spring是一个依赖注入(dependency injection)框架。所有的内容都是关于 bean 的定义及其依赖关系。

      ComponentScan 要做的就是告诉 Spring 从哪里找到 bean。

      @ComponentScan({ "com.a.aa", "com.a.bb" })
      @ComponentScan(basePackages = { "com.a.aa", "com.a.bb" })
      @ComponentScan("com.a")
      @ComponentScan(value = "com.a")
      @ComponentScan(basePackages = {"com.a"})
      @ComponentScan(basePackageClasses=Test.class)
      • SpringBoot 在写启动类的时候如果不使用@ComponentScan 指明对象扫描范围,默认指扫描当前启动类所在的包里的对象
      • 如果当前启动类没有包,则在启动时会报错:Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package 错误,因为启动类不能直接放在 main/java 文件夹下,必须要建一个包把它放进去或者使用 @ComponentScan 指明要扫描的包;
      • 如果有一些 bean 所在的包,不在主类的包及其下级包,那么你需要手动加上 @ComponentScan 注解并指定那个bean 所在的包。
      <context:component-scan base-package="com.a.aa, com.a.bb" />
      
    3. @SpringBootApplication

      @SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration + @ComponentScan

      @SpringBootApplication 
      public class ApplicationMain { 
      public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
      }
      }
    4. @EnableAutoConfiguration

      能够自动配置 spring 的上下文,试图猜测和配置你想要的 bean 类,通常会自动根据你的类路径和你的 bean 定义自动配置。

  • 相关阅读:
    Android Volley入门到精通:定制自己的Request
    Android高效加载大图、多图解决方案,有效避免程序OOM
    Android Volley入门到精通:使用Volley加载网络图片
    Android Volley入门到精通:初识Volley的基本用法
    彻底理解ThreadLocal
    Android中Parcelable接口用法
    Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解
    Storm流处理项目案例
    021 使用join()将数组转变为字符串
    020 $.each的使用
  • 原文地址:https://www.cnblogs.com/dins/p/java-annotation.html
Copyright © 2020-2023  润新知