自定义注解类和使用
元注解
元注解是用于修饰注解的注解,一般用于指定某个注解生命周期以及作用目标等信息。
@Target:注解的作用目标
ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
ElementType.FIELD:允许作用在属性字段上
ElementType.METHOD:允许作用在方法上
ElementType.PARAMETER:允许作用在方法参数上
ElementType.CONSTRUCTOR:允许作用在构造器上
ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
ElementType.ANNOTATION_TYPE:允许作用在注解上
ElementType.PACKAGE:允许作用在包上
@Retention:注解的生命周期
RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
RetentionPolicy.RUNTIME:永久保存,可以反射获取
@Documented:注解是否应当被包含在 JavaDoc 文档中
当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。
@Inherited:是否允许子类继承该注解
我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。
JAVA 的内置三大注解
@Override
它没有任何的属性,所以并不能存储任何其他信息。它只能作用于方法之上,编译结束后将被丢弃。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Deprecated
@SuppressWarnings
自定义注解类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoTableName {
String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoFieldColumn {
String value() default "";
}
使用注解类
@AnnoTableName("T_STUDENT")
public class AnnoStudent {
@AnnoFieldColumn("NAME")
private String name;
@AnnoFieldColumn("POST_ADDRESS")
private String postAddress;
private Integer gender;
...省略get set
}
public class Demo01 {
@Test
public void test01() {
AnnoStudent annoStudent = new AnnoStudent();
annoStudent.setName("小明");
annoStudent.setPostAddress("wu");
String selectSql = getSelectSql(annoStudent);
System.err.println(selectSql);
// select NAME, POST_ADDRESS from T_STUDENT where 1=1 and NAME=小明 and POST_ADDRESS=wu
}
public static String getSelectSql(AnnoStudent annoStudent) {
Class<? extends AnnoStudent> clazz = annoStudent.getClass();
AnnoTableName annotationTable = clazz.getAnnotation(AnnoTableName.class);
if (annotationTable == null) {
throw new RuntimeException("参数有错!");
}
Field[] fieldArr = clazz.getDeclaredFields();
String columnPart = "";
String wherePart = " where 1=1";
for (int i = 0; i < fieldArr.length; i++) {
Field field = fieldArr[i];
AnnoFieldColumn annotationField = field.getAnnotation(AnnoFieldColumn.class);
if (annotationField == null) {
continue;
}
String valueField = annotationField.value();
if (i == 0) {
columnPart += valueField;
} else {
columnPart += ", " + valueField;
}
try {
field.setAccessible(true);
Object object = field.get(annoStudent);
if (object != null) {
wherePart += " and " + valueField + "=" + object;
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
StringBuffer sb = new StringBuffer();
sb.append("select ");
String valueTable = annotationTable.value();
sb.append(columnPart + " from " + valueTable + wherePart);
return sb.toString();
}
}
结合spring使用注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
public @interface Strategy {
String[] names();
}
@Strategy(names="messageStrategyDefault")
@Component
public class MessageStrategyDefault {}
/**
*
* 寻找使用 @Strategy 注解 的类,并打印相关信息
*
*/
@Component
public class StrategyExplain implements ApplicationListener<ContextRefreshedEvent> {
private String annotationName = Strategy.class.getName();
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
_initial(applicationContext);
}
private void _initial(ApplicationContext applicationContext) {
if (!(applicationContext instanceof BeanDefinitionRegistry)) {
throw new RuntimeException("applicationContext is not instanceof BeanDefinitionRegistry");
}
List<AnnotatedBeanDefinition> beanDefinitionList = _getAnnotationBeanDefinition(applicationContext, applicationContext.getBeanDefinitionNames(), annotationName);
beanDefinitionList.forEach(item->{
Map<String, Object> annotationAttributes = item.getMetadata().getAnnotationAttributes(annotationName);
String[] names = (String[])annotationAttributes.get("names");
String tip = String.format("%s annotationName[name]=%s", item.getBeanClassName(), names[0]);
System.err.println(tip);
});
}
private List<AnnotatedBeanDefinition> _getAnnotationBeanDefinition(ApplicationContext applicationContext, String[] beanDefinitionNames, String annotationName) {
List<AnnotatedBeanDefinition> beanDefinitionList = new ArrayList<>();
for(String beanDefinitionName: beanDefinitionNames) {
BeanDefinition beanDefinition = ((BeanDefinitionRegistry) applicationContext).getBeanDefinition(beanDefinitionName);
if (!(beanDefinition instanceof AnnotatedBeanDefinition)) {
continue;
}
AnnotationMetadata metadata = ((AnnotatedBeanDefinition) beanDefinition).getMetadata();
if(metadata.hasAnnotation(annotationName)) {
beanDefinitionList.add((AnnotatedBeanDefinition) beanDefinition);
}
}
return beanDefinitionList;
}
}