註解的使用方法以及自定義註解
註解的簡單用法
/*
* 註解是給編譯器看的
* 如下是複寫的Object類的方法
* Override代表此方法是複寫的
* 如果父類中沒有此方法,會報編譯錯誤
*/
@Override
public boolean equals(Object obj){
return super.equals(obj);
}
/*
* 表示該方法已過時
*/
@Deprecated
public void add(){
}
/*
* 去掉由於沒有使用泛型而出現的警告
*/
@SuppressWarnings("rawtypes")
public void doit(){
List list=new ArrayList<>();
System.out.println(list);
}
自定義註解
新建一個註解類
/**
* @author Administrator
* 使用註解可以替代配置文件,將原來配置文件中的信息
* 在註解中描述
*/
public @interface Annotation1 {
String name();//聲明一個String屬性
//聲明一個枚舉屬性,並給出默認值
Gender gender() default Gender.FEMALE;
Class cla();//聲明一個類屬性
//聲明一個註解屬性,這樣可以嵌套數據
MyAnnotation2 my2();
//聲明一個數組屬性,不能這樣寫default new int[];
int [] arr() default {1,2,4};
//註解中不能使用集合類型屬性
/*
* Invalid type List for the annotation attribute Annotation1.ss;
* only primitive type, String, Class, annotation, enumeration
* are permitted or 1-dimensional arrays thereof
*/
//List ss();
}
Annotation1中的註解屬性MyAnnotation2
public @interface MyAnnotation2 {
String name();
}
使用該註解類
/*
* 使用自定義annotation
*/
@Annotation1(name="zhangsan",gender=Gender.MALE,cla=String.class,my2=@MyAnnotation2(name="xxx"))
public void doaa(){
}
註解中名稱爲“value”的屬性,可以直接賦值,但是這只是在註解中只有這一個屬性的情況下
public @interface MyAnnotation3 {
String value();
}
//使用MyAnnotation3
@MyAnnotation3("xxx")
public void dobb(){
}
使用註解替代配置文件,將原來配置文件中的信息在註解中描述
存儲信息的註解類
/*
* @Retention包含RetentionPolicy,通過它指定域
* RetentionPolicy.CLASS
* 把註解記錄在class文件中,jvm不會保留註解,這是默認值
* RetentionPolicy.RUNTIME
* 把註解記錄在class文件中,jvm會保留註解
* RetentionPolicy.SOURCE
* 編譯器直接丟棄這種策略註釋
*/
//下面四個是元Annotation,也就是修飾Annotation的Annotation
//-------------------------------------------
//定義了該Annotation被保留的時間(一定要在這裏聲明作用域,否則運行時不能得到該註解)
@Retention(RetentionPolicy.RUNTIME)
//這個是指定註解用於修飾類的哪個成員
@Target({ElementType.METHOD,ElementType.PACKAGE})
@Documented//被該註解修飾的註解類將被javadoc工具提取成文檔
@Inherited//被它修飾的註解將具有繼承性
//--------------------------------------------------------
public @interface DBInfoAnnotation {
String url();
String username();
String pwd();
}
在下面的類中使用上面的自定義註解(只是用來模擬,並沒有真正連接數據庫)
public class DBConnect {
@DBInfoAnnotation(url="jdbc:mysql://localhost:3306/test",username="root",pwd="123")
public Connection getConnection(String url,String username,String pwd){
System.out.println(url);
System.out.println(username);
System.out.println(pwd);
return null;
}
}
使用反射獲取註解中配置的信息,並執行getConnection方法
public class Demo2 {
public static void main(String[] args) throws Exception{
Class cla=DBConnect.class;
//得到需要運行的方法
Method method= cla.getMethod("getConnection", String.class, String.class, String.class);
DBInfoAnnotation di= method.getAnnotation(DBInfoAnnotation.class);
String url=di.url();
String username=di.username();
String pwd=di.pwd();
method.invoke(cla.newInstance(), url,username,pwd);
}
}
執行上面的demo,可以打印出DBConnect的getConnection方法使用
註解配置的信息
使用註解將實體類傳給方法或類屬性供其使用
實體類
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
傳遞該實體類的註解
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectPerson {
String name();
int age();
}
操作該實體類的Dao
public class PersonDao {
@InjectPerson(name="laoli",age=23) private Person person;
public Person getPerson() {
return person;
}
@InjectPerson(name="laowang",age=23)
public void setPerson(Person person) {
this.person = person;
}
}
—————通過註解將person傳給方法
/**
* @author Administrator
* 通過註解將person傳給方法
*/
public class Test {
public static void main(String[] args) throws IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException, InvocationTargetException {
//1.得到要注入的屬性
PropertyDescriptor pd=new PropertyDescriptor("person", PersonDao.class);
//2.得到要注入的屬性需要的類型
Class cla= pd.getPropertyType();//person
//3.得到創建屬性需要的對象
Object person=cla.newInstance();
//4得到屬性的寫方法(set)
Method setPerson=pd.getWriteMethod();
//5反射方法上聲明的註解
InjectPerson inject= setPerson.getAnnotation(InjectPerson.class);
//6得到註解上聲明的信息,填充person對象
Method[] methods=inject.getClass().getMethods();
for(Method m:methods){
String methodName=m.getName();
try{
//如果沒有該方法會拋出異常(methodName)
Field f= Person.class.getDeclaredField(methodName);
Object value= m.invoke(inject, null);//得到註解上配置的屬性的值
f.setAccessible(true);//如果實體類中的成員變量爲private,必須進行此操作
f.set(person, value);
}catch(Exception e){
continue;
}
}
//7把填充了數據的person通過setPerson方法整到personDao上
PersonDao dao=new PersonDao();
setPerson.invoke(dao, person);//執行personDao的setPerson方法
System.out.println(dao.getPerson().getName());//打印一下,測試是否成功獲取
}
}
————–通過註解將person傳給屬性
/**
* @author Administrator
* 通過註解將person傳給屬性
*/
public class Test2 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IntrospectionException {
// TODO Auto-generated method stub
//1.得到需要注入的屬性
Field f=PersonDao.class.getDeclaredField("person");
//2得到屬性需要的類型
Class cla=f.getType();
System.out.println(cla);
//3創建person
Person person=(Person) cla.newInstance();
//4反射屬性的註解
InjectPerson inject=f.getAnnotation(InjectPerson.class);
//5並用註解的信息填充person
Method m[]=inject.getClass().getMethods();
for(Method ms:m){
String methodName=ms.getName();
//看person對象上有沒有註解與之對應的屬性
try{
//如果沒有該方法會拋出異常(methodName)
PropertyDescriptor pd=new PropertyDescriptor(methodName,Person.class);
Method set=pd.getWriteMethod();
set.invoke(person, ms.invoke(inject, null));
}catch(Exception e){
continue;
}
}
//6.把person賦給dao
PersonDao dao=new PersonDao();
f.setAccessible(true);
f.set(dao, person);
System.out.println(dao.getPerson().getName());
}