首页>>后端>>Spring->java中自定义注解详解?

java中自定义注解详解?

时间:2023-12-02 本站 点击:0

java 自定义的注解有什么作用

自定义注解,可以应用到反射中,比如自己写个小框架。

如实现实体类某些属性不自动赋值,或者验证某个对象属性完整性等

本人自己用过的验证属性值完整性:

@Target(ElementType.FIELD)   

@Retention(RetentionPolicy.RUNTIME)

public @interface IgnoreProperty {

}

然后实体类中:

public class TarResearch implements Serializable{

 @IgnoreProperty

 private static final long serialVersionUID = 1L;

 @IgnoreProperty

private  Integer researchId;

 @IgnoreProperty

 private TarUser userId;

 private String version;

 private String grade;

....

   } 

然后action类中  

// 验证数据完整性

  ClassTarResearch  userClass = TarResearch .class;

  Field[] field = userClass.getDeclaredFields();

  for (int i = 0; i  field.length; i++) {

   if (field[i].getAnnotation(IgnoreProperty.class) != null) {

    continue;

   }

   String fie = field[i].getName().substring(0, 1).toUpperCase()

     + field[i].getName().substring(1);

   Method method = userClass.getMethod("get" + fie);

   Object obj = method.invoke(u);

   if (obj == null) {

    sendResponseMsg(response, "数据错误");

    return null;

   }

  }

如何创建,使用以及解析自定义注解

首先要想使用自定义注解,必须创建自己的注解类

右键项目,new - Annotation

然后在注解里定义自己的方法,该方法是别的类使用注解时需要填的属性

package com.sy.demo.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Table {public String value();}

注:如果只有一个方法时,应该用value()来指定方法名,这样就可以直接简写@Table("xxx")而不是@Table(aaa="xxx");

其中注解类上的注解称为元注解

@Target(ElementType.TYPE)

@Target的意思是,该注解类是放在什么位置的,是放在类上、字段上还是方法上,ElementType.TYPE意思是只能放在类上或接口上,ElementType.FIELD意思是只能放在字段上等等。

如果有多个位置选择可以这么写:

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

意思是作用域,一般写RUNTIME就行

@Documented

意思是是否在生成JavaDoc时加入该注解类,这个看情况写不写

还有其他元注解,想要研究的就自己研究吧

定义完自定义注解了,下面就是使用的时候了

package com.sy.demo.entity;import com.sy.demo.annotation.Column;import com.sy.demo.annotation.Table;@Table("tdb_user")public class User {@Column("id")private Long id;@Column("email")private String email;@Column("password")private String password;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

在这里我定义了一个实体类,用于表示用户信息,其中还是用了一个@Column类,代码如下

package com.sy.demo.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Column {public String value();}

由代码可知,@Column是放在field上的

使用也使用完了,下面该是解析的时候了。

package com.sy.demo.util;import java.lang.reflect.Field;import com.sy.demo.annotation.Column;import com.sy.demo.annotation.Table;public class SqlUtil {private static final String EMPTY = "";@SuppressWarnings("unchecked")public static String getSql(Object object) {StringBuilder sb = new StringBuilder();ClassObject c;boolean isExist;Column column;String columnName;String getMethodName;Object columnValue;String[] strs;try {c = (ClassObject) object.getClass();isExist = c.isAnnotationPresent(Table.class);if (!isExist) {return EMPTY;}Table table = c.getAnnotation(Table.class);sb.append(" SELECT * FROM " + table.value() + " WHERE 1 = 1 " );Field[] fields = c.getDeclaredFields();for (Field field: fields) {isExist = field.isAnnotationPresent(Column.class);if (!isExist) {continue;}column = field.getAnnotation(Column.class);columnName = column.value();getMethodName = "get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);columnValue = c.getMethod(getMethodName, new Class[0]).invoke(object, new Object[0]);if (columnValue == null) {continue;}if (columnValue instanceof String) {columnValue = (String)columnValue;if(((String) columnValue).contains(",")) {sb.append("AND " + columnName + " IN (");strs = ((String) columnValue).split(",");for(String str: strs) {sb.append("'" + str + "',");}sb.deleteCharAt(sb.length() - 1);sb.append(") ");} else {sb.append("AND " + columnName + " = '" + columnValue + "' ");}} else if (columnValue instanceof Integer || columnValue instanceof Long) {sb.append("AND " + columnName + " = " + columnValue + " ");}}} catch (Exception e) {e.printStackTrace();}return sb.toString();}}

解析的时候用的是反射机制,可能看着比较麻烦比较乱,而且也新手可能也不太理解,在用的时候会发现其实还是挺方便的。

原理解释根据反射找到User类,在判断是否有注解,接着拼接sql什么的

整个列子项目中完整的代码如下(有许多步骤测试用例,懒得删了,全贴出来吧)

Controller

package com.sy.demo.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.sy.demo.entity.User;import com.sy.demo.service.IUserService;@Controller@RequestMapping("hello")public class UserController {@Autowiredprivate IUserService hService;@RequestMapping(value = "demo1")public String demo1() {return "demo1";}@SuppressWarnings("deprecation")@RequestMapping(value = "demo2")public String demo2() {return hService.test();}@RequestMapping(value = "demo3")@ResponseBodypublic String demo3() {User user = new User();user.setId(1L);user.setEmail("mr_songyang1990@163.com");user.setPassword("1q2w3e4r,123456,aaaaa");return hService.getUser(user);}@RequestMapping(value = "demo4")@ResponseBodypublic String demo4() {User user = new User();user.setId(1L);user.setEmail("mr_songyang1990@163.com");user.setPassword("1q2w3e4r,123456,aaaaa");return hService.getUser2(user);}}

service:

package com.sy.demo.service;import com.sy.demo.entity.User;public interface IUserService {@Deprecatedpublic String test();public String getUser(User user);public String getUser2(User user);}

package com.sy.demo.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.sy.demo.entity.User;import com.sy.demo.repository.IUserRepository;import com.sy.demo.service.IUserService;@Service("hService")public class UserServiceImpl implements IUserService {@Autowiredprivate IUserRepository hRepository;@Deprecated@Overridepublic String test() {return "demo2";}@Overridepublic String getUser(User user) {return hRepository.queryUser(user);}@Overridepublic String getUser2(User user) {return hRepository.queryUser2(user);}}

Repository

package com.sy.demo.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.sy.demo.entity.User;import com.sy.demo.repository.IUserRepository;import com.sy.demo.service.IUserService;@Service("hService")public class UserServiceImpl implements IUserService {@Autowiredprivate IUserRepository hRepository;@Deprecated@Overridepublic String test() {return "demo2";}@Overridepublic String getUser(User user) {return hRepository.queryUser(user);}@Overridepublic String getUser2(User user) {return hRepository.queryUser2(user);}}

package com.sy.demo.repository.impl;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.springframework.stereotype.Repository;import com.sy.demo.entity.User;import com.sy.demo.repository.IUserRepository;import com.sy.demo.util.DBUtil;import com.sy.demo.util.SqlUtil;@Repository("hRepository")public class UserRepositoryImpl implements IUserRepository {public String queryUser(User user) {String sql = SqlUtil.getSql(user);System.out.println(sql);return sql;}@Overridepublic String queryUser2(User user) {StringBuilder sb = new StringBuilder();String sql = SqlUtil.getSql(user);System.out.println(sql);PreparedStatement ps = DBUtil.getPreparedStatement(sql);Long id;String email;String password;try {ResultSet rs = ps.executeQuery();while (rs.next()) {id = rs.getLong("id");email = rs.getString("email");password = rs.getString("password");sb.append("ID:").append(id).append(", email:").append(email).append(", password:").append(password).append("br/");}} catch (SQLException e) {e.printStackTrace();}return sb.toString();}}

entity:

package com.sy.demo.entity;import com.sy.demo.annotation.Column;import com.sy.demo.annotation.Table;@Table("tdb_user")public class User {@Column("id")private Long id;@Column("email")private String email;@Column("password")private String password;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

annotation

package com.sy.demo.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Table {public String value();}

package com.sy.demo.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Column {public String value();}

util工具类

package com.sy.demo.util;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;public class DBUtil {public static final String URL = "jdbc:mysql://localhost:3306/db_test";public static final String USERNAME = "root";public static final String PASSWORD = "root";public static Connection conn = null;public static MysqlDataSource dataSource;static {dataSource = new MysqlDataSource();dataSource.setUser(USERNAME);dataSource.setPassword(PASSWORD);dataSource.setURL(URL);}public static PreparedStatement getPreparedStatement(String sql) {try {conn = dataSource.getConnection();return conn.prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return null;}}

package com.sy.demo.util;import java.lang.reflect.Field;import com.sy.demo.annotation.Column;import com.sy.demo.annotation.Table;public class SqlUtil {private static final String EMPTY = "";@SuppressWarnings("unchecked")public static String getSql(Object object) {StringBuilder sb = new StringBuilder();ClassObject c;boolean isExist;Column column;String columnName;String getMethodName;Object columnValue;String[] strs;try {c = (ClassObject) object.getClass();isExist = c.isAnnotationPresent(Table.class);if (!isExist) {return EMPTY;}Table table = c.getAnnotation(Table.class);sb.append(" SELECT * FROM " + table.value() + " WHERE 1 = 1 " );Field[] fields = c.getDeclaredFields();for (Field field: fields) {isExist = field.isAnnotationPresent(Column.class);if (!isExist) {continue;}column = field.getAnnotation(Column.class);columnName = column.value();getMethodName = "get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);columnValue = c.getMethod(getMethodName, new Class[0]).invoke(object, new Object[0]);if (columnValue == null) {continue;}if (columnValue instanceof String) {columnValue = (String)columnValue;if(((String) columnValue).contains(",")) {sb.append("AND " + columnName + " IN (");strs = ((String) columnValue).split(",");for(String str: strs) {sb.append("'" + str + "',");}sb.deleteCharAt(sb.length() - 1);sb.append(") ");} else {sb.append("AND " + columnName + " = '" + columnValue + "' ");}} else if (columnValue instanceof Integer || columnValue instanceof Long) {sb.append("AND " + columnName + " = " + columnValue + " ");}}} catch (Exception e) {e.printStackTrace();}return sb.toString();}}

如何实现自定义注解

首先,定义一个注解:

package com.guxiang.test;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

首先自定义一个 myTest注解

/**

 * @author guxiang

 * @date 2016年12月24日 下午10:22:11

 * 自定义的myTest注解

 */

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})

public @interface MyTest {

    long time() default -1;

}

其次,写一个类用于被myTest注解,实现测试:

package com.guxiang.test;

public class SomeDaoImpl {

    public void save(){

        System.out.println("保存了数据");

    }

    public void update(){

        System.out.println("更新了数据");

    }

}

写一个测试类 这个类 引用myTest注解:

package com.guxiang.test;

public class SomeDaoImplTest {

    private SomeDaoImpl dao= new SomeDaoImpl();

    /**

     * 测试添加

     */

    @MyTest

    public void testAdd(){

        dao.save();

    }

    @MyTest

    public void testUpdate(){

        dao.update();

    }

最后,写一个myTestRunner类使用反射实现注解的功能:

package com.guxiang.test;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

// 反射注解

public class MyTestRunner {

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {

        Class clazz = SomeDaoImplTest.class;

        Method[] ms = clazz.getMethods();

        for (Method method : ms) {

            boolean hasMyTest = method.isAnnotationPresent(MyTest.class);

            if (hasMyTest) {

                method.invoke(clazz.newInstance(), null);

            }

        }

    }

}

Java自定义注解

你的注解是定义在 com.bestTeam.ifu.annotation这个包下的

可是你引用的时候,怎么变成 com$annotation$ValidIdentitySign 这个了?确认你在使用的时候没有写错?


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/10009.html