代碼前的`@WebFilter`、`@WebInitParam`是**Java註解**,JDK 1.5引入,本質是**接口一種特殊形式**,用於為代碼提供元數據。本文系統講解註解三大作用、元註解、內置註解與自定義實戰。
| 分類 | 階段 | 機制 | 典型例子 |
|---|---|---|---|
| 編寫文檔 | 源碼期 | javadoc工具提取生成API文檔 | `@author`、`@version`、`@param`、`@return`、`@see` |
| 代碼分析/檢查 | 編譯期/靜態分析 | 編譯器/IDE/檢查工具(ErrorProne、SpotBugs)讀取註解執行邏輯 | `@Override`、`@Deprecated`、`@SuppressWarnings`、`@NonNull`、`@Nullable` |
| 運行時處理 | 運行時 | 反射API讀取註解屬性,驅動框架邏輯(DI、AOP、映射、驗證) | Spring `@Autowired`、`@Transactional`、JPA `@Entity`、JAX-RS `@Path`、本例 `@WebFilter` |
@Target(ElementType.TYPE) // 作用目標:類/接口/方法/字段/參數/構造器/局部變量/註解/包/類型參數/類型使用
@Retention(RetentionPolicy.RUNTIME) // 生命周期:SOURCE(源碼丟棄) / CLASS(編譯保留,默認) / RUNTIME(運行時反射可見)
@Documented // 包含在javadoc中
@Inherited // 子類自動繼承父類此註解(僅针對TYPE)
@Repeatable(Container.class) // 同一位置可重複使用 (Java 8+)
public @interface MyAnnotation { ... }
// 原問題代碼即為此類
@WebFilter(
filterName = "authority",
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "encoding", value = "UTF-8"), // 建議UTF-8
@WebInitParam(name = "loginPage", value = "/login.jsp"),
@WebInitParam(name = "proLogin", value = "/proLogin.jsp")
}
)
public class AuthorityFilter implements Filter {
// initParams 可在 init(FilterConfig config) 中獲取
// config.getInitParameter("encoding")
@Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
// 認證邏輯
chain.doFilter(req, res);
}
}
// 1. 定義
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogExecutionTime {
String value() default ""; // 自定義屬性
}
// 2. 使用
public class Service {
@LogExecutionTime("用戶登錄")
public void login() { ... }
}
// 3. 運行時處理(AOP切面/代理/掃描器)
public class AnnotationProcessor {
public void process(Object bean) {
for (Method m : bean.getClass().getDeclaredMethods()) {
if (m.isAnnotationPresent(LogExecutionTime.class)) {
LogExecutionTime ann = m.getAnnotation(LogExecutionTime.class);
String label = ann.value();
// 織入邏輯:計時、日誌、權限...
long start = System.nanoTime();
m.invoke(bean);
System.out.println(label + " 耗時: " + (System.nanoTime() - start) + "ns");
}
}
}
}
註解本質:代碼層面的結構化元數據,將「說明」變為「可計算、可驅動邏輯」的機器可讀信息。