? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 艷艷耶??:個(gè)人主頁
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 個(gè)人專欄 :《Spring與Mybatis集成整合》
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?生活的理想,為了不斷更新自己 !
1.前言
1.1.什么是注解
Annontation是Java5開始引入的新特征,中文名稱叫注解。
它提供了一種安全的類似注釋的機(jī)制,用來將任何的信息或元數(shù)據(jù)(metadata)與程序元素(類、方法、成員變量等)進(jìn)行關(guān)聯(lián)。為程序的元素(類、方法、成員變量)加上更直觀、更明了的說明,這些說明信息是與程序的業(yè)務(wù)邏輯無關(guān),并且供指定的工具或框架使用。Annontation像一種修飾符一樣,應(yīng)用于包、類型、構(gòu)造方法、方法、成員變量、參數(shù)及本地變量的聲明語句中。
Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說明、配置的功能。注解不會也不能影響代碼的實(shí)際邏輯,僅僅起到輔助性的作用。
1.2.注解的用處
- ?生成文檔。這是最常見的,也是java 最早提供的注解。常用的有@param @return 等
- 跟蹤代碼依賴性,實(shí)現(xiàn)替代配置文件功能。比如Dagger 2 依賴注入,未來java 開發(fā),將大量注解配置,具有很大用處;
- 在編譯時(shí)進(jìn)行格式檢查。如@override 放在方法前,如果你這個(gè)方法并不是覆蓋了超類方法,則編譯時(shí)就能檢查出。
?1.3.注解的原理
注解本質(zhì)是一個(gè)繼承了Annotation 的特殊接口,其具體實(shí)現(xiàn)類是Java 運(yùn)行時(shí)生成的動態(tài)代理類。而我們通過反射獲取注解時(shí),返回的是Java 運(yùn)行時(shí)生成的動態(tài)代理對象$Proxy1。通過代理對象調(diào)用自定義注解(接口)的方法,會最終調(diào)用AnnotationInvocationHandler 的invoke 方法。該方法會從memberValues 這個(gè)Map 中索引出對應(yīng)的值。而memberValues 的來源是Java 常量池。
2.注解的案列:
??2.1?案例一(獲取類與方法上的注解值)
? ? ? ? ????????定義一個(gè)類:
package com.sy.annotation.pi;
public enum TranscationModel {
Read, Write, ReadWrite //定義三個(gè)實(shí)例,可以將它看作類
}
? ? ? ? ? ? ? ?寫三個(gè)注解:
package com.sy.annotation;
import java.lang.annotation.*;
/**
* MyAnnotation1注解可以用在類、接口、屬性、方法上
* 注解運(yùn)行期也保留
* 不可繼承
*/
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
String name();
}
package com.sy.annotation;
import java.lang.annotation.*;
/**
* MyAnnotation2注解可以用在方法上
* 注解運(yùn)行期也保留
* 不可繼承
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
TranscationModel model() default TranscationModel.ReadWrite;
}
package com.sy.annotation;
import java.lang.annotation.*;
/**
* @author shenyan
*
* MyAnnotation3注解可以用在方法上
* 注解運(yùn)行期也保留
* 可繼承
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
TranscationModel[] models() default TranscationModel.ReadWrite;
}
創(chuàng)建幾個(gè)方法使用這些注解
package com.sy.annotation.Demo1;
import com.sy.annotation.MyAnnotation1;
import com.sy.annotation.MyAnnotation2;
import com.sy.annotation.MyAnnotation3;
import com.sy.annotation.TranscationModel;
/**
* @author shenyan
*
* 獲取類與方法上的注解值
*/
@MyAnnotation1(name = "艷艷耶")
public class Demo1 {
@MyAnnotation1(name = "csdn")
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");
}
}
最后,進(jìn)行測試
?2.2??案例二(獲取類屬性上的注解屬性值,默認(rèn)值的賦予)
? ? ??? 自定義一個(gè)注解,并賦予默認(rèn)值:
package com.sy.annotation.Demo2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author shenyan
* /
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
String value() default "默認(rèn)value值";
String what() default "這里是默認(rèn)的what屬性對應(yīng)的值";
}
? 建立類測試:
? ? ? ? ? ? ??? 有些兩個(gè)值都賦予了,有些只賦予了一個(gè)
package com.sy.annotation.Demo2;
/**
* @author shenyan
*
* 獲取類屬性上的注解屬性值
*/
public class Demo2 {
@TestAnnotation(value = "這就是value對應(yīng)的值_msg1", what = "這就是what對應(yīng)的值_msg1")
private static String msg1;
@TestAnnotation("這就是value對應(yīng)的值1")
private static String msg2;
@TestAnnotation(value = "這就是value對應(yīng)的值2")
private static String msg3;
@TestAnnotation(what = "這就是what對應(yīng)的值")
private static String msg4;
}
???測試結(jié)果:
?? 2.3??案例三(獲取參數(shù)修飾注解對應(yīng)的屬性值,非空注解)
? ? ? ? ? ? ? ??同樣,先建立一個(gè)非空注解
package com.sy.annotation;
import java.lang.annotation.*;
/**
* @author shenyan
*
* 非空注解:使用在方法的參數(shù)上,false表示此參數(shù)可以為空,true不能為空
*/
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
boolean value() default false;
}
?建立方法,進(jìn)行測試:
package com.sy.annotation.Demo3;
import com.sy.annotation.IsNotNull;
/**
* @author shenyan
*
* 獲取參數(shù)修飾注解對應(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);
}
}
測試類:
方法1:
方法2:
方法3:
3.AOP結(jié)合自定義注解案例
? ? ? ??配置相關(guān)AOP? pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
? ? ? ?applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1. 注解式開發(fā) -->
<!-- 注解驅(qū)動 -->
<context:annotation-config/>
<!-- 用注解方式注入bean,并指定查找范圍:com.javaxl.ssh2及子子孫孫包-->
<context:component-scan base-package="com.zking"/>
<!--開啟動態(tài)代理-->
<aop:aspectj-autoproxy />
</beans>
?定義一個(gè)標(biāo)志日志的注解
package com.sy.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author shenyan
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String desc();
}
再創(chuàng)建一個(gè)切面類?LogAspect
,用于實(shí)現(xiàn)日志記錄的邏輯。
package com.sy.annotation.aop;
import com.sy.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;
/**
* @author shenyan
*/
@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.sy.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)對象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:"+myLog.desc());
System.out.println("【目標(biāo)對象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:" + myLog.desc());
}
}
在方法上運(yùn)用日志注解
package com.sy.annotation.aop;
import com.sy.annotation.MyLog;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author shenyan
*/
@Controller
public class LogController {
@RequestMapping("/myLog")
@MyLog(desc = "這是結(jié)合spring aop知識,講解自定義注解應(yīng)用的一個(gè)案例")
public void testLogAspect(){
System.out.println("這里隨便來點(diǎn)啥");
}
}
運(yùn)行結(jié)果:?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?今日分享結(jié)束!文章來源:http://www.zghlxwxcb.cn/news/detail-732235.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-732235.html
到了這里,關(guān)于【springMvc】自定義注解的使用方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!