Java 注解

一、注解的概念

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

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

  1. 以 @interface 关键字定义
  2. 注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
  3. 成员赋值是通过 @Annotation(name=value) 的形式。
  4. 注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
Copy
@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 此类的工具文档化。

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

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

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

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

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

    标明注解的修饰目标。

    Copy
    // 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);

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

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

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

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

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

3.3 Hibernate#

  1. @Entity

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

    必须使用。

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

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

    可选使用。

    Copy
    @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 的错误提示信息。

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

    Copy
    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. 自定义验证信息

    Copy
    @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 {}; }

    校验器:

    Copy
    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 配置文件。

    Copy
    <beans> <bean id = "car" class="com.test.Car"> <property name="wheel" ref = "wheel"></property> </bean> <bean id = "wheel" class="com.test.Wheel"></bean> </beans>
    Copy
    @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。

    Copy
    @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 注解自动注册,无需其他代码。

    Copy
    @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。

    Copy
    @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 所在的包。
    Copy
    <context:component-scan base-package="com.a.aa, com.a.bb" />
  3. @SpringBootApplication

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

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

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

posted @   和风细羽  阅读(194)  评论(0编辑  收藏  举报
编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· Supergateway:MCP服务器的远程调试与集成工具
· C# 13 中的新增功能实操
点击右上角即可分享
微信分享提示
文章目录