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 这个了?确认你在使用的时候没有写错?