目錄
前言
一、自定義注解
1.Java注解簡(jiǎn)介
2. 注解的用處
3. 為什么要用注解
4.自定義注解的應(yīng)用場(chǎng)景
5. 注解的分類
6.如何定義并使用自定義注解
7.自定義注解三種使用案例
案例一:
案例二:
案例三:
二、Aop自定義注解的應(yīng)用 ?
1 .自定義注解類
2.切面類
3.Controller層
前言
隨著Web開發(fā)的發(fā)展,越來(lái)越多的企業(yè)開始使用SpringMVC框架來(lái)構(gòu)建自己的Web應(yīng)用程序。在開發(fā)過(guò)程中,為了提高代碼的可讀性和可維護(hù)性,我們經(jīng)常需要自定義注解。本文將介紹如何編寫一個(gè)自定義注解,并通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)演示如何使用它。
一、自定義注解
1.Java注解簡(jiǎn)介
Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說(shuō)明、配置的功能。 注解相關(guān)類都包含在java.lang.annotation包中。
2. 注解的用處
-
配置和元數(shù)據(jù):注解可以用于配置和描述類、方法、字段等元素的特性和行為。例如,我們可以使用注解來(lái)指定數(shù)據(jù)庫(kù)表的名稱、字段的長(zhǎng)度、方法的訪問(wèn)權(quán)限等。
-
編譯時(shí)檢查:注解可以用于在編譯時(shí)對(duì)代碼進(jìn)行靜態(tài)檢查,以確保代碼的正確性和合規(guī)性。例如,我們可以使用注解來(lái)標(biāo)記過(guò)時(shí)的方法或類,編譯器會(huì)在編譯時(shí)給出警告。
-
運(yùn)行時(shí)處理:注解可以在運(yùn)行時(shí)通過(guò)反射機(jī)制獲取到,并根據(jù)注解的定義來(lái)執(zhí)行相應(yīng)的邏輯。例如,我們可以使用注解來(lái)實(shí)現(xiàn)自定義的AOP(面向切面編程)邏輯,或者在某些條件下動(dòng)態(tài)地修改方法的行為。
-
文檔生成:注解可以用于生成文檔,以便開發(fā)者更好地理解代碼的含義和使用方式。例如,我們可以使用注解來(lái)標(biāo)記API的使用示例、參數(shù)的說(shuō)明等。
3. 為什么要用注解
-
減少樣板代碼:通過(guò)使用注解,我們可以將一些重復(fù)性的代碼抽象為注解,從而減少冗余的代碼量。
-
提高代碼可讀性:注解可以用于描述代碼的特性和行為,使代碼更加易于理解和閱讀。
-
增強(qiáng)代碼的可維護(hù)性:通過(guò)使用注解,我們可以將一些與業(yè)務(wù)邏輯無(wú)關(guān)的代碼與業(yè)務(wù)邏輯分離,使代碼更加模塊化和可維護(hù)。
-
提高開發(fā)效率:使用注解可以簡(jiǎn)化一些繁瑣的操作,提高開發(fā)效率。
4.自定義注解的應(yīng)用場(chǎng)景
應(yīng)用場(chǎng)景十分廣泛,舉例說(shuō)明幾個(gè):
- 在SpringMVC中,我們可以使用自定義注解來(lái)標(biāo)記Controller中的方法,以實(shí)現(xiàn)請(qǐng)求的映射和處理。
- 在MyBatis中,我們可以使用自定義注解來(lái)標(biāo)記Mapper接口中的方法,以實(shí)現(xiàn)SQL語(yǔ)句的映射和執(zhí)行。
- 在JUnit中,我們可以使用自定義注解來(lái)標(biāo)記測(cè)試方法,以實(shí)現(xiàn)自動(dòng)化測(cè)試的執(zhí)行。
5. 注解的分類
-
JDK元注解:元注解是用于注解其他注解的注解,它可以用于指定注解的作用范圍、生命周期等。常見的元注解有
@Target
、@Retention
、@Documented
等。 -
JDK基本注解:標(biāo)準(zhǔn)注解是Java提供的一些常用注解,例如
@Override
、@Deprecated
、@SuppressWarnings
等。 -
自定義注解:自定義注解是開發(fā)者根據(jù)自己的需求定義的注解,用于實(shí)現(xiàn)特定的功能或邏輯。
-
框架注解:框架注解是一些常用框架提供的注解,用于實(shí)現(xiàn)框架的特定功能。例如,Spring框架提供的
@Autowired
、@RequestMapping
等注解。
6.如何定義并使用自定義注解
自定義注解的定義非常簡(jiǎn)單,只需要使用@interface
關(guān)鍵字即可。
package com.ctb.utils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
String value() default "";
}
我們定義了一個(gè)名為
CustomAnnotation
的注解。該注解可以應(yīng)用于方法上,并且在運(yùn)行時(shí)保留。注解中還定義了一個(gè)名為value
的屬性,默認(rèn)為空字符串。
使用自定義注解非常簡(jiǎn)單,只需要在需要標(biāo)記的地方使用注解即可。
@CustomAnnotation("這是一個(gè)自定義注解示例")
public void doSomething() {
// 執(zhí)行一些操作
}
7.自定義注解三種使用案例
案例一:
1. 定義一個(gè)枚舉類:用來(lái)表示一組固定的值。
package com.ctb.model;
public enum TranscationModel {
Read, Write, ReadWrite
}
2. 定義三個(gè)不同注解方式的類:
MyAnnotation1 :??
package com.ctb.annotation;
import java.lang.annotation.*;
/**
* MyAnnotation1注解可以用在類、接口、屬性、方法上
* 注解運(yùn)行期也保留
* 不可繼承
*/
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
String name();
}
MyAnnotation2?:??
package com.ctb.annotation;
import com.ctb.model.TranscationModel;
import java.lang.annotation.*;
/**
* MyAnnotation2注解可以用在方法上
* 注解運(yùn)行期也保留
* 不可繼承
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
TranscationModel model() default TranscationModel.ReadWrite;
}
MyAnnotation3?:??
package com.ctb.annotation;
import com.ctb.model.TranscationModel;
import java.lang.annotation.*;
/**
* MyAnnotation3注解可以用在方法上
* 注解運(yùn)行期也保留
* 可繼承
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
TranscationModel[] models() default TranscationModel.ReadWrite;
}
?Demo1測(cè)試類 :?獲取類與方法上的注解值
package com.ctb.annotation.demo;
import com.ctb.annotation.MyAnnotation1;
import com.ctb.annotation.MyAnnotation2;
import com.ctb.annotation.MyAnnotation3;
import com.ctb.model.TranscationModel;
/**
* 獲取類與方法上的注解值
*/
@MyAnnotation1(name = "abc")
public class Demo1 {
@MyAnnotation1(name = "xyz")
private Integer age;
@MyAnnotation2(model = TranscationModel.Read)
public void list() {
System.out.println("list");
}
@MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
public void edit() {
System.out.println("edit");
}
}
?Demo1Test測(cè)試類:
package com.ctb.annotation.demo;
import com.ctb.annotation.MyAnnotation1;
import com.ctb.annotation.MyAnnotation2;
import com.ctb.annotation.MyAnnotation3;
import com.ctb.model.TranscationModel;
import org.junit.Test;
public class Demo1Test {
@Test
public void list() throws Exception {
// 獲取類上的注解
MyAnnotation1 annotation1 = Demo1.class.getAnnotation(MyAnnotation1.class);
System.out.println(annotation1.name());//abc
// 獲取方法上的注解
MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);
System.out.println(myAnnotation2.model());//Read
// 獲取屬性上的注解
MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
System.out.println(myAnnotation1.name());// xyz
}
@Test
public void edit() throws Exception {
MyAnnotation3 myAnnotation3 = Demo1.class.getMethod("edit").getAnnotation(MyAnnotation3.class);
for (TranscationModel model : myAnnotation3.models()) {
System.out.println(model);//Read,Write
}
}
}
@Ingerited的使用
@Inherited注解是Java中的元注解之一,用于控制注解的繼承性。當(dāng)一個(gè)類或接口被@Inherited注解修飾時(shí),它的子類將自動(dòng)獲得該注解。但需要注意的是,@Inherited只對(duì)類和接口有效,對(duì)方法、字段等無(wú)效。
普通的類繼承是指子類可以繼承父類的所有非private的成員變量和方法,包括構(gòu)造器。子類可以使用父類中的方法和屬性,也可以重寫父類的方法,在其基礎(chǔ)上進(jìn)行擴(kuò)展或修改。
?執(zhí)行l(wèi)ist方法測(cè)試結(jié)果
執(zhí)行edit方法測(cè)試結(jié)果?
案例二:
1. 自定義注解類:
package com.ctb.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
String value() default "默認(rèn)value值";
String what() default "這里是默認(rèn)的what屬性對(duì)應(yīng)的值";
}
2. 定義測(cè)試類:獲取類屬性上的注解屬性值
package com.ctb.annotation.demo2;
import com.ctb.annotation.TestAnnotation;
/**
* 獲取類屬性上的注解屬性值
*/
public class Demo2 {
@TestAnnotation(value = "這就是value對(duì)應(yīng)的值_msg1", what = "這就是what對(duì)應(yīng)的值_msg1")
private static String msg1;
@TestAnnotation("這就是value對(duì)應(yīng)的值1")
private static String msg2;
@TestAnnotation(value = "這就是value對(duì)應(yīng)的值2")
private static String msg3;
@TestAnnotation(what = "這就是what對(duì)應(yīng)的值")
private static String msg4;
}
?3. 測(cè)試
package com.ctb.annotation.demo2;
import com.ctb.annotation.TestAnnotation;
import org.junit.Test;
public class Demo2Test {
@Test
public void test1() throws Exception {
TestAnnotation msg1 = Demo2.class.getDeclaredField("msg1").getAnnotation(TestAnnotation.class);
System.out.println(msg1.value());
System.out.println(msg1.what());
}
@Test
public void test2() throws Exception{
TestAnnotation msg2 = Demo2.class.getDeclaredField("msg2").getAnnotation(TestAnnotation.class);
System.out.println(msg2.value());
System.out.println(msg2.what());
}
@Test
public void test3() throws Exception{
TestAnnotation msg3 = Demo2.class.getDeclaredField("msg3").getAnnotation(TestAnnotation.class);
System.out.println(msg3.value());
System.out.println(msg3.what());
}
@Test
public void test4() throws Exception{
TestAnnotation msg4 = Demo2.class.getDeclaredField("msg4").getAnnotation(TestAnnotation.class);
System.out.println(msg4.value());
System.out.println(msg4.what());
}
}
案例三:
1.創(chuàng)建自定義注解:
package com.ctb.annotation;
import java.lang.annotation.*;
/**
* 非空注解:使用在方法的參數(shù)上,false表示此參數(shù)可以為空,true不能為空
*/
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
boolean value() default false;
}
2. 創(chuàng)建測(cè)試類:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-732081.html
package com.ctb.annotation.demo3;
import com.ctb.annotation.IsNotNull;
/**
* 獲取參數(shù)修飾注解對(duì)應(yīng)的屬性值
*/
public class Demo3 {
public void hello1(@IsNotNull(true) String name) {
System.out.println("hello:" + name);
}
public void hello2(@IsNotNull String name) {
System.out.println("hello:" + name);
}
}
3. 測(cè)試文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-732081.html
package com.ctb.annotation.demo3;
import com.ctb.annotation.IsNotNull;
import org.junit.Test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class Demo3Test {
@Test
public void hello1() throws Exception {
Demo3 demo3 = new Demo3();
for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {
IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
if(annotation != null){
System.out.println(annotation.value());//true
}
}
}
@Test
public void hello2() throws Exception {
Demo3 demo3 = new Demo3();
for (Parameter parameter : demo3.getClass().getMethod("hello2", String.class).getParameters()) {
IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
if(annotation != null){
System.out.println(annotation.value());//false
}
}
}
@Test
public void hello3() throws Exception {
// 模擬瀏覽器傳遞到后臺(tái)的參數(shù) 解讀@requestParam
String name = "zs";
Demo3 demo3 = new Demo3();
Method method = demo3.getClass().getMethod("hello1", String.class);
for (Parameter parameter : method.getParameters()) {
IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
if(annotation != null){
System.out.println(annotation.value());//true
if (annotation.value() && !"".equals(name)){
method.invoke(demo3,name);
}
}
}
}
}
二、Aop自定義注解的應(yīng)用 ?
1 .自定義注解類
package com.ctb.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String desc();
}
2.切面類
package com.ctb.aspect;
import com.ctb.annotation.MyLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyLogAspect {
private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
/**
* 只要用到了com.javaxl.p2.annotation.springAop.MyLog這個(gè)注解的,就是目標(biāo)類
*/
@Pointcut("@annotation(com.ctb.annotation.MyLog)")
private void MyValid() {
}
@Before("MyValid()")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
logger.debug("[" + signature.getName() + " : start.....]");
System.out.println("[" + signature.getName() + " : start.....]");
MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
logger.debug("【目標(biāo)對(duì)象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:"+myLog.desc());
System.out.println("【目標(biāo)對(duì)象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:" + myLog.desc());
}
}
3.Controller層
package com.ctb.web;
import com.ctb.annotation.MyLog;
import org.springframework.stereotype.Component;
@Component
public class LogController {
@MyLog(desc = "這是結(jié)合spring aop知識(shí),講解自定義注解應(yīng)用的一個(gè)案例")
public void testLogAspect(){
System.out.println("記錄日志...");
}
}
到了這里,關(guān)于SpringMVC之自定義注解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!