日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java spring注解_spring注解是如何实现的?

發(fā)布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java spring注解_spring注解是如何实现的? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

注解呢,是java本身自帶的一個東西,它基于java的接口進行實現(xiàn),是一種特殊的接口類型,通常對于注解來說,三種情況,一個是在編譯前就會被丟棄的,一個是編譯后留在class中的,另一種是會一直存在,運行的時候注解也會被保留,而框架的注解一般都是第三種。

Class對象,Method對象,Parameter對象,Constructor對象等java反射對象通常都具有g(shù)etAnnotation方法可以直接獲取保留到運行時的注解實例,就像這樣:

@Component

class AnnoTest {

}

這樣的一個類,有一個component注解,我們可以通過這樣:

Component comp = AnnoTest.class.getAnnotation(Component.class);

Annotation[] annotations = AnnoTest.class.getAnnotations();

// 其實還有兩個注解的get方法,你可以自己去看,這里不多說。

就直接得到了class上面的注解。

注解和普通接口不一樣,他聲明的語法比較特別,public @interface 注解名這個樣子。為了標識注解的使用范圍,你需要使用一些java提供的幾個其他注解,這些用來描述注解的注解被稱為元注解。

@Retention,保留范圍(在源碼中存在,還是在字節(jié)碼里面,還是一直留到運行環(huán)境),一般是Runtime,

@Target 注解的作用對象,類型還是字段還是方法,這個注解是寫在什么地方的。

@Inherited 是否可以繼承此注解,這個注解僅僅在針對類的注解中起效,如果一個類繼承了使用了含有他的注解的父類,那么這個類也會擁有父類的那個注解。

@Documented 注解再生成JavaDoc的時候是否會被寫入Javadoc。

總之,這樣就是有一個注解了,比如這樣:

@Retention(RUNTIME)

@Target(ElementType.TYPE)

public @interface Component {

/*** 組件名稱* @return*/

String name() default "";

/*** 組件創(chuàng)建類型* @return*/

Scope scope() default Scope.SINGLE;

}

這里要特別的說下注解接口的方法:這些方法由返回值,方法名稱構(gòu)成,具體的值是你寫注解的時候填進去的,例如上述注解的name,實際上是你在使用注解的時候放在@component(name="xxxx")這里面的那個name,這些方法可以使用default指定一個默認返回值,即,你在使用注解的時候沒有填寫這個東西,會返回的內(nèi)容。

接下來,你要用反射的手法拿到這些帶有注解的class,method,field之類的,然后get到他們的注解,然后對注解進行處理,無論是aop還是注入,按照你的需要自己實現(xiàn)。

這里有一個例子,這個是仿照spring進行properties文件進行值注入的方法,他通過讀取class的configProperties注解得到properties文件的位置,然后注入到bean的字段中。

public Object prcess(Object target, Definition definition, IFactory factory) {

Class> clazz = definition.getClazz();

ConfigProperties config = clazz.getAnnotation(ConfigProperties.class);

if (config == null) {

return target;

}

String location = config.value();

if (!location.startsWith(File.separator)) {

location = File.separator + location;

}

URL url = clazz.getResource(location);

Properties props = new Properties();

try {

props.load(url.openStream());

// 這個只是對properties的封裝,就當他是普通properties好了PropertiesConfig propsConfig = new PropertiesConfig();

propsConfig.setProperties(props);

Set keys = props.stringPropertyNames();

for (String propName : keys) {

String fieldName = propName.replace(config.prefix() + ".", "");

try {

//按照properties的key,去掉前綴后讀取類的字段FieldField field = clazz.getDeclaredField(fieldName);

// 開啟操作權(quán)限field.setAccessible(true);

// 字段不是string型就需要轉(zhuǎn)換一下if (field.getType() != String.class) {

// 獲取類型轉(zhuǎn)換器ICovertor covertor = Covertors

.getCovertor(String.class, field.getType());

if (covertor != null) {

// 轉(zhuǎn)換類型并且注入field.set(target, covertor

.covert(propsConfig.get(propName)));

} else {

// 反向獲取類型轉(zhuǎn)換器(這里的轉(zhuǎn)換器接口//是雙向的,其實這樣區(qū)分方向轉(zhuǎn)換不是很好,//但是我現(xiàn)在沒有來得及改他。covertor = Covertors

.getCovertorRev(field.getType(),

String.class);

// 轉(zhuǎn)換并注入, 其實這里應(yīng)該判空,// 但是當時應(yīng)該是我忘記了field.set(target, covertor.

covertRev(propsConfig.get(propName)));

}

} else {

// 類型一致,直接注入field.set(target, propsConfig.get(propName));

}

} catch (Exception e) {

// 注入失敗也無所謂,無視這個字段下一個注入}

}

} catch (IOException e) {

throw new RuntimeException(e);

}

return target;

}

注解接口:

@Retention(RUNTIME)

@Target(TYPE)

@Component

public @interface ConfigProperties {

String value();

String prefix();

}

附一個近期手寫的ioc容器,仿springboot,用注解驅(qū)動的那種,雖然水平比較菜,但是注解還是用了不少的,哦,對了,這個代碼需要Java11才行。仿制IOC的GitHub?github.com

總結(jié)

以上是生活随笔為你收集整理的java spring注解_spring注解是如何实现的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。