先看一個普通的例子
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 = "test"; static String encoding = "UTF-8"; static String loginName = "root"; static String password = "admin"; 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()); } }
自定義注解@JDBCConfig
接下來,就要把DBUtil這個類改造成為支持自定義注解的方式。 首先創建一個注解JDBCConfig
1. 創建注解類型的時候即不使用class也不使用interface,而是使用@interface
2. 元注解
@Target({METHOD,TYPE}) 表示這個注解可以用用在類/接口上,還可以用在方法上
@Retention(RetentionPolicy.RUNTIME) 表示這是一個運行時注解,即運行起來之后,才獲取注解中的相關信息,而不像基本注解如@Override 那種不用運行,在編譯時eclipse就可以進行相關工作的編譯時注解。
@Inherited 表示這個注解可以被子類繼承
@Documented 表示當執行javadoc的時候,本注解會生成相關文檔
3. 注解元素,這些注解元素就用於存放注解信息,在解析的時候獲取出來
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(); }
注解方式DBUtil
有了自定義注解@JDBCConfig之后,我們就把非注解方式DBUtil改造成為注解方式DBUtil。
如例所示,數據庫相關配置信息本來是以屬性的方式存放的,現在改為了以注解的方式,提供這些信息了。
注: 目前只是以注解的方式提供這些信息,但是還沒有解析,接下來進行解析
package util;
import anno.JDBCConfig; @JDBCConfig(ip = "127.0.0.1", database = "test", encoding = "UTF-8", loginName = "root", password = "admin") public class DBUtil { static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
解析注解
接下來就通過反射,獲取這個DBUtil這個類上的注解對象
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();
后續就一樣了,根據這些配置信息得到一個數據庫連接Connection實例。
package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import anno.JDBCConfig; @JDBCConfig(ip = "127.0.0.1", database = "test", encoding = "UTF-8", loginName = "root", password = "admin") 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 { Connection c = getConnection(); System.out.println(c); } }
注解的分類
根據注解的作用域@Retention,注解分為
RetentionPolicy.SOURCE: Java源文件上的注解
RetentionPolicy.CLASS: Class類文件上的注解
RetentionPolicy.RUNTIME: 運行時的注解
按照注解的來源,也是分為3類
1. 內置注解 如@Override ,@Deprecated 等等
2. 第三方注解,如Hibernate, Struts等等
3. 自定義注解,如仿hibernate的自定義注解
在工作中,大部分都是使用第三方注解, 當然第三方注解本身就是自定義注解。 本教程的主要作用是幫助大家理解這些第三方注解是如何工作的,讓大家用得心里踏實一些。
推薦一個極好的教程:https://how2j.cn/k/annotation/annotation-brief/1055.html?p=49538
另一個例子:https://www.jianshu.com/p/f85e5212be55