自定义注解
自定义注解需要利用元注解,元注解是基本注解,用来修饰别的注解。关于元注解本文后部分详细讲解。
- 非注解方式DBUtil
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtil {
static String ip = "127.0.0.1";
static int port = 3306;
static String database = "how2java";
static String encoding = "UTF-8";
static String loginName = "root";
static String password = "123456";
static{
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
return DriverManager.getConnection(url, loginName, password);
}
public static void main(String[] args) throws SQLException {
System.out.println(getConnection());
}
}
- 注解方式的DBUtil
package anno;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({METHOD,TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface JDBCConfig {
String ip();
int port() default 3306;
String database();
String encoding();
String loginName();
String password();
}
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import anno.JDBCConfig;
@JDBCConfig(ip = "127.0.0.1",
database = "how2java",
encoding = "UTF-8",
loginName = "root",
password = "123456")
public class DBUtil {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException, NoSuchMethodException, SecurityException {
JDBCConfig config = DBUtil.class.getAnnotation(JDBCConfig.class);
String ip = config.ip();
int port = config.port();
String database = config.database();
String encoding = config.encoding();
String loginName = config.loginName();
String password = config.password();
String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
return DriverManager.getConnection(url, loginName, password);
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, SQLException {
System.out.println(getConnection());
}
}
元注解
元注解是一种基本注解,用来修饰其他注解。
@Target
@Retention
@Inherited
@Documented
@Repeatable
-
@Target
@Target({METHOD,TYPE}),表示他可以用在方法和类型上(类和接口),但是不能放在属性等其他位置。 可以选择的位置列表如下:
ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包 -
@Retention
表示注解的声明周期,可传入参数值为RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME,每个参数含义看下面源码注释。
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang.annotation;
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
- @Inherited
表示该注解具有继承性。子类可以获得父类上的该注解。具体见源码注释。 - @Documented
在用javadoc命令生成API文档后,文档里会出现该注解说明。 - @Repeatable
当没有@Repeatable修饰的时候,注解在同一个位置,只能出现一次,超过一次会报错。使用@Repeatable注解,使得同一位置可重复使用某种注解如下示例:
package anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class TestRepeatableAnnotation {
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Persons {
Person[] value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Persons.class) // Persons相当于容器注解,存放多个Person注解的值
public @interface Person {
String role() default "";
}
@Person(role = "Teacher")
@Person(role = "Scientist")
@Person(role = "Mathematician")
public void fun() {
try {
Person[] persons = this.getClass()
.getMethod("fun")
.getAnnotationsByType(Person.class);
for(Person person : persons) {
System.out.println(person.role());
}
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new TestRepeatableAnnotation().fun();
}
}
参考资料
[1] How2J
[2] 《疯狂Java讲义(第4版)》 李刚
[3] 《Java核心技术 卷I》
[4] 《Java核心技术 卷II》
[5] https://blog.csdn.net/briblue/article/details/73824058