文章目錄
- 1. 反射與注解
- 2. 動態代理
- 3. 實踐:編寫動態代理示例
- 4. 注解定義與使用
- 5. 動態代理
- 6. 小結與思考
1. 反射與注解
- 注解:注解是 Java 提供的用于在代碼中添加元數據的機制。它不會影響程序的執行,但可以在運行時通過反射獲取和處理。
- 反射讀取注解:
- 通過 Class、Method、Field 等反射 API 獲取注解信息。
- 注解可以用于類、方法、字段等。
2. 動態代理
- 動態代理的概念:動態代理是 Java 提供的一種機制,可以在運行時創建接口的代理實例,并且可以在方法調用前后插入額外的操作。
- 使用 Proxy 類:java.lang.reflect.Proxy 類提供了創建代理對象的靜態方法。
- 代理接口:通過 InvocationHandler 接口來定義代理對象的行為。
3. 實踐:編寫動態代理示例
- 創建一個接口,使用動態代理為其生成代理對象。
- 在代理方法中加入日志打印,打印每個方法的調用時間。
4. 注解定義與使用
注解的定義通常采用 @interface 關鍵字,例如:
// 定義一個自定義注解
import java.lang.annotation.*;@Target(ElementType.METHOD) // 這個注解應用在方法上
@Retention(RetentionPolicy.RUNTIME) // 運行時可以反射獲取
public @interface Log {String value() default "日志記錄";
}
如何通過反射讀取注解:
假設有如下類及方法上使用了注解:
import java.lang.annotation.*;public class Example {// 應用自定義注解@Log(value = "執行sayHello方法")public void sayHello() {System.out.println("Hello, World!");}public static void main(String[] args) {try {// 獲取 sayHello 方法的 Class 對象Method method = Example.class.getMethod("sayHello");// 判斷該方法是否有 Log 注解if (method.isAnnotationPresent(Log.class)) {// 獲取注解的值Log log = method.getAnnotation(Log.class);System.out.println("注解內容: " + log.value());}// 調用方法method.invoke(new Example());} catch (Exception e) {e.printStackTrace();}}
}
輸出結果:
注解內容: 執行sayHello方法
Hello, World!
解釋:
- @Log 注解定義了一個 value 屬性,在 sayHello() 方法上使用。
- 通過反射獲取方法 sayHello,使用 isAnnotationPresent 判斷是否應用了注解,然后獲取注解并打印 value 屬性。
5. 動態代理
動態代理的原理
- 動態代理是一種在運行時創建代理對象的技術。通過 java.lang.reflect.Proxy 類和 InvocationHandler 接口,Java 實現了動態代理機制。
- 通過動態代理可以增強原對象的功能,比如記錄日志、權限控制等。
創建動態代理的基本步驟
1.定義接口:代理類需要實現接口。
2.實現 InvocationHandler:InvocationHandler 用于處理代理對象的方法調用。
3.使用 Proxy.newProxyInstance():創建代理對象。
示例:為某個接口創建代理對象,并在方法調用前后打印日志
1. 定義接口
public interface Person {void sayHello();void work();
}
2. 實現接口
public class PersonImpl implements Person {@Overridepublic void sayHello() {System.out.println("Hello from Person!");}@Overridepublic void work() {System.out.println("Person is working.");}
}
3. 創建 InvocationHandler 實現類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class LoggingHandler implements InvocationHandler {private Object target;public LoggingHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在方法執行前打印日志System.out.println("Method " + method.getName() + " is about to be called.");// 執行目標方法Object result = method.invoke(target, args);// 在方法執行后打印日志System.out.println("Method " + method.getName() + " was called.");return result;}
}
4. 使用 Proxy 創建代理對象
import java.lang.reflect.Proxy;public class DynamicProxyExample {public static void main(String[] args) {Person person = new PersonImpl(); // 創建目標對象// 創建代理對象Person proxyPerson = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class},new LoggingHandler(person));// 使用代理對象調用方法proxyPerson.sayHello();proxyPerson.work();}
}
輸出結果:
Method sayHello is about to be called.
Hello from Person!
Method sayHello was called.
Method work is about to be called.
Person is working.
Method work was called.
解釋:
- 通過 Proxy.newProxyInstance() 創建了一個 Person 接口的代理對象。代理對象會調用 LoggingHandler 的 invoke 方法。
- LoggingHandler 通過 method.invoke(target, args) 調用實際的目標方法,并在方法調用前后打印日志。
6. 小結與思考
1.反射與注解:
- 注解是一個非常強大的元數據機制,可以在運行時動態地獲取類和方法的相關信息。常見應用包括框架開發、AOP(面向切面編程)等。
2.動態代理: - 動態代理是面向切面編程中的一個核心技術,它允許我們在運行時動態地為接口生成代理,并對方法執行前后進行增強(如日志、權限控制等)。
- 動態代理廣泛應用于 Java 框架,如 Spring 的 AOP(面向切面編程)。