Spring註解原理的詳細剖析與實現
一、註解的基本概念和原理及其簡單實用
註解(Annotation)提供了一種安全的類似註釋的機制,為我們在程式碼中新增資訊提供了一種形式化得方法,使我們可以在稍後某個時刻方便的使用這些資料(通過解析註解來使用這些資料),用來將任何的資訊或者元資料與程式元素(類、方法、成員變數等)進行關聯。其實就是更加直觀更加明瞭的說明,這些說明資訊與程式業務邏輯沒有關係,並且是供指定的工具或框架使用的。Annotation像一種修飾符一樣,應用於包、型別、構造方法、方法、成員變數、引數及本地變數的申明語句中。
Annotation其實是一種介面。通過java的反射機制相關的API來訪問Annotation資訊。相關類(框架或工具中的類)根據這些資訊來決定如何使用該程式元素或改變它們的行為。Java語言直譯器在工作時會忽略這些Annotation,因此在JVM中這些Annotation是“不起作用”的,只能通過配套的工具才能對這些Annotation型別的資訊進行訪問和處理。
Annotation和interface的異同:
2、 Annotation型別、方法定義是獨特的、受限制的。Annotation型別的方法必須申明為無引數、無異常丟擲的。這些方法定義了Annotation的成員:方法名稱為了成員名,而方法返回值稱為了成員的型別。而方法返回值必須為primitive型別、Class型別、列舉型別、Annotation型別或者由前面型別之一作為元素的一位陣列。方法的後面可以使用default和一個預設數值來申明成員的預設值,null不能作為成員的預設值,這與我們在非Annotation型別中定義方法有很大不同。Annotation型別和他的方法不能使用Annotation型別的引數,成員不能是generic。只有返回值型別是Class的方法可以在Annotation型別中使用generic,因為此方法能夠用類轉換將各種型別轉換為Class。
3、 Annotation型別又與介面有著近似之處。它們可以定義常量、靜態成員型別(比如列舉型別定義)。Annotation型別也可以如介面一般被實現或者繼承。
* 元註解@Target,@Retention,@Documented,@Inherited
*
* @Target 表示該註解用於什麼地方,可能的 ElemenetType 引數包括:
* ElemenetType.CONSTRUCTOR 構造器宣告
* ElemenetType.FIELD 域宣告(包括 enum 例項)
* ElemenetType.LOCAL_VARIABLE 區域性變數宣告
* ElemenetType.METHOD 方法宣告
* ElemenetType.PACKAGE 包宣告
* ElemenetType.PARAMETER 引數宣告
* ElemenetType.TYPE 類,介面(包括註解型別)或enum宣告
*
* @Retention 表示在什麼級別儲存該註解資訊。可選的 RetentionPolicy 引數包括:
* RetentionPolicy.SOURCE 註解將被編譯器丟棄
* RetentionPolicy.CLASS 註解在class檔案中可用,但會被VM丟棄
* RetentionPolicy.RUNTIME VM將在執行期也保留註釋,因此可以通過反射機制讀取註解的資訊。
*
* @Documented 將此註解包含在 javadoc 中
*
* @Inherited 允許子類繼承父類中的註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
下面的示例來簡單的講述spring註解原理:
本例實現了在set方法上和在欄位屬性上註解的處理解析。
1、定義註解
Java程式碼- package com.yt.annotation;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * @Description:定義註解
- * @ClassName: ZxfResource
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-6-7
- */
- // 在執行時執行
- @Retention(RetentionPolicy.RUNTIME)
- // 註解適用地方(欄位和方法)
- @Target({ ElementType.FIELD, ElementType.METHOD })
- public @interface ZxfResource {
- //註解的name屬性
- public String name() default "";
- }
2、帶有註解的服務類
Java程式碼- package com.yt.annotation;
- /**
- * @Description: 帶有註解的服務
- * @ClassName: UserDaoImpl
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-6-7
- */
- public class UserServiceImpl {
- public UserDaoImpl userDao;
- public User1DaoImpl user1Dao;
- // 欄位上的註解,可以配置name屬性
- @ZxfResource
- public User2DaoImpl user2Dao;
- // set方法上的註解,帶有name屬性
- @ZxfResource(name = "userDao")
- public void setUserDao(UserDaoImpl userDao) {
- this.userDao = userDao;
- }
- // set方法上的註解,沒有配置name屬性
- @ZxfResource
- public void setUser1Dao(User1DaoImpl user1Dao) {
- this.user1Dao = user1Dao;
- }
- public void show() {
- userDao.show();
- user1Dao.show1();
- user2Dao.show2();
- System.out.println("這裡是Service方法........");
- }
- }
3、要注入的DAO
Java程式碼- package com.yt.annotation;
- /**
- * @Description: 要注入的DAo類
- * @ClassName: UserDaoImpl
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-6-7
- */
- public class UserDaoImpl {
- String name ;
- public void show(){
- System.out.println("這裡是dao方法........");
- }
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id = "userDao" class="com.yt.annotation.UserDaoImpl" />
- <bean id = "user1Dao" class="com.yt.annotation.User1DaoImpl" />
- <bean id = "user2Dao" class="com.yt.annotation.User2DaoImpl" />
- <bean id = "userService" class = "com.yt.annotation.UserServiceImpl" />
- </beans>
4、註解處理器
Java程式碼- package com.yt.annotation;
- import java.beans.Introspector;
- import java.beans.PropertyDescriptor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import org.apache.log4j.Logger;
- import org.dom4j.Document;
- import org.dom4j.DocumentException;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- /**
- * @Description: spring中的註解原理
- * @ClassName: ClassPathXMLApplicationContext
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-6-3
- */
- public class ClassPathXMLApplicationContext {
- Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class);
- List<BeanDefine> beanList = new ArrayList<BeanDefine>();
- Map<String, Object> sigletions = new HashMap<String, Object>();
- public ClassPathXMLApplicationContext(String fileName) {
- //讀取配置檔案中管理的bean
- this.readXML(fileName);
- //例項化bean
- this.instancesBean();
- //註解處理器
- this.annotationInject();
- }
- /**
- * 讀取Bean配置檔案
- * @param fileName
- * @return
- */
- @SuppressWarnings("unchecked")
- public void readXML(String fileName) {
- Document document = null;
- SAXReader saxReader = new SAXReader();
- try {
- ClassLoader classLoader =
- Thread.currentThread().getContextClassLoader();
- document = saxReader.read(classLoader.getResourceAsStream(fileName));
- Element beans = document.getRootElement();
- for (Iterator<Element> beansList = beans.elementIterator();
- beansList.hasNext();) {
- Element element = beansList.next();
- BeanDefine bean = new BeanDefine(
- element.attributeValue("id"),
- element.attributeValue("class"));
- beanList.add(bean);
- }
- } catch (DocumentException e) {
- log.info("讀取配置檔案出錯....");
- }
- }
- /**
- * 例項化Bean
- */
- public void instancesBean() {
- for (BeanDefine bean : beanList) {
- try {
- sigletions.put(bean.getId(),
- Class.forName(bean.getClassName()).newInstance());
- } catch (Exception e) {
- log.info("例項化Bean出錯...");
- }
- }
- }
- /**
- * 註解處理器
- * 如果註解ZxfResource配置了name屬性,則根據name所指定的名稱獲取要注入的例項引用,
- * 如果註解ZxfResource;沒有配置name屬性,則根據屬性所屬型別來掃描配置檔案獲取要
- * 注入的例項引用
- *
- */
- public void annotationInject(){
- for(String beanName:sigletions.keySet()){
- Object bean = sigletions.get(beanName);
- if(bean!=null){
- this.propertyAnnotation(bean);
- this.fieldAnnotation(bean);
- }
- }
- }
- /**
- * 處理在set方法加入的註解
- * @param bean 處理的bean
- */
- public void propertyAnnotation(Object bean){
- try {
- //獲取其屬性的描述
- PropertyDescriptor[] ps =
- Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
- for(PropertyDescriptor proderdesc : ps){
- //獲取所有set方法
- Method setter = proderdesc.getWriteMethod();
- //判斷set方法是否定義了註解
- if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){
- //獲取當前註解,並判斷name屬性是否為空
- ZxfResource resource = setter.getAnnotation(ZxfResource.class);
- String name ="";
- Object value = null;
-
if(resource.name()!=
相關推薦
Spring註解原理的詳細剖析與實現
一、註解的基本概念和原理及其簡單實用 註解(Annotation)提供了一種安全的類似註釋的機制,為我們在程式碼中新增資訊提供了一種形式化得方法,使我們可以在稍後某個時刻方便的使用這些資料(通過解析註解來使用這些資料),用來將任何的資訊或者元資料與程式元素(類、方法、成員變
【機器學習】演算法原理詳細推導與實現(一):線性迴歸
【機器學習】演算法原理詳細推導與實現(一):線性迴歸 今天我們這裡要講第一個有監督學習演算法,他可以用於一個迴歸任務,這個演算法叫做 線性迴歸 房價預測 假設存在如下 m 組房價資料: 面積(m^2) 價格(萬元) 82.35 193 65.00 213 114.20 255 75.
【機器學習】演算法原理詳細推導與實現(二):邏輯迴歸
【機器學習】演算法原理詳細推導與實現(二):邏輯迴歸 在上一篇演算法中,線性迴歸實際上是 連續型 的結果,即 \(y\in R\) ,而邏輯迴歸的 \(y\) 是離散型,只能取兩個值 \(y\in \{0,1\}\),這可以用來處理一些分類的問題。 logistic函式 我們可能會遇到一些分類問題,例如想要劃
【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯
【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯 在上一篇演算法中,邏輯迴歸作為一種二分類的分類器,一般的迴歸模型也是是判別模型,也就根據特徵值來求結果概率。形式化表示為 \(p(y|x;\theta)\),在引數 \(\theta\) 確定的情況下,求解條件概率 \(p(y|x)\) 。通俗的解釋為:
【機器學習】演算法原理詳細推導與實現(四):支援向量機(上)
【機器學習】演算法原理詳細推導與實現(四):支援向量機(上) 在之前的文章中,包括線性迴歸和邏輯迴歸,都是以線性分界線進行分割劃分種類的。而本次介紹一種很強的分類器【支援向量機】,它適用於線性和非線性分界線的分類方法。 函式間隔概念 為了更好的理解非線性分界線,區別兩種分界線對於分類的直觀理解,第一種直觀理解
【機器學習】演算法原理詳細推導與實現(五):支援向量機(下)
【機器學習】演算法原理詳細推導與實現(五):支援向量機(下) 上一章節介紹了支援向量機的生成和求解方式,能夠根據訓練集依次得出\(\omega\)、\(b\)的計算方式,但是如何求解需要用到核函式,將在這一章詳細推導實現。 核函式 在講核函式之前,要對上一章節得到的結果列舉出來。之前需要優化的凸函式為: \[
【機器學習】演算法原理詳細推導與實現(六):k-means演算法
【機器學習】演算法原理詳細推導與實現(六):k-means演算法 之前幾個章節都是介紹有監督學習,這個章節介紹無監督學習,這是一個被稱為k-means的聚類演算法,也叫做k均值聚類演算法。 聚類演算法 在講監督學習的時候,通常會畫這樣一張圖: 這時候需要用logistic迴歸或者SVM將這些資料分成正負兩
【機器學習】演算法原理詳細推導與實現(七):決策樹演算法
# 【機器學習】演算法原理詳細推導與實現(七):決策樹演算法 在之前的文章中,對於介紹的分類演算法有[邏輯迴歸演算法](https://www.cnblogs.com/TTyb/p/10976291.html)和[樸素貝葉斯演算法](https://www.cnblogs.com/TTyb/p/109890
Atitit spring註解事務的demo與程式碼說明 目錄 1.1. Spring框架中,要如何實現事務?有一個註解,@EnableTransactionManagement 1 1.2. 事務管理
Atitit spring註解事務的demo與程式碼說明 目錄 1.1. Spring框架中,要如何實現事務?有一個註解,@EnableTransactionManagement 1 1.2. 事務管理 99.99999%都是使用了xml來配置的 1 1.3.
Spring IoC 容器的設計與實現原理
上一篇文章講解的是IOC的原理,這一篇文章主要講解Spring IoC 容器的設計與實現原理 1.spring的IOC容器 在 Spring IoC 容器的設計中,容器有兩個系列,可以看成是容器的具體表現形式: BeanFactory 簡單容器:實現了容器的基本
Spring方法注入的使用與實現原理
# 一、前言 這幾天為了更詳細地瞭解``Spring``,我開始閱讀``Spring``的官方文件。說實話,之前很少閱讀官方文件,就算是讀,也是讀別人翻譯好的。但是最近由於準備春招,需要了解很多知識點的細節,網上幾乎搜尋不到,只能硬著頭皮去讀官方文件。雖然我讀的這個``Spring`
AES加密演算法的詳細介紹與實現
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "aes.h" /** * S盒 */ static const int S[16][16] = { 0x63, 0
Skip List(跳躍表)原理詳解與實現
#include<stdio.h> #include<stdlib.h> #define MAX_LEVEL 10 //最大層數 //節點 typedef struct nodeStructure { int key; int value
spring boot 原理、demo 與打包執行
Spring Boot的背景,我們為什麼要用它,它能給我們帶來什麼遍便利? 回首我們以前使用Spring框架的時候,我們需要首先在(如果你使用Maven的話)pom檔案中增加對相關
隨機森林 演算法原理詳解與實現步驟
#include <cv.h> // opencv general include file #include <ml.h> // opencv machine learning include file #include <stdio.h>
Spring Security原理學習--簡介與示例(一)
一、簡介 Spring Security 提供了基於javaEE的企業應有個你軟體全面的安全服務。這裡特別強調支援使用SPring框架構件的專案,Spring框架是企業軟體開發javaEE方案的領導者。如果你還沒有使用Spring來開發企業應用程式,我們熱忱的鼓
讀書筆記——新一代高效視訊編碼H.265HEVC原理、標準與實現
1.視訊編碼標準 視訊編碼標準只是規定了編碼碼流的語法語義和解碼器,只要求視訊編碼後的碼流符合標準的語法結構,解碼器就可以根據碼流的語法語義進行正常解碼。因此,符合某個視訊編碼標準的編碼器是有很大自由度的,只要編碼後的碼流符合標準的規定即可。
動態規劃之揹包問題原理詳細推導及其實現
貪心演算法:(1) 給定n個物品,物品價值分別為P1,P2,…,Pn,物品重量分別W1,W2, …, Wn,揹包容量為M。每種物品可部分裝入到揹包中。輸出X1,X2,…,Xn,0<Xi<1, 使得
高效能的分散式記憶體快取伺服器系統——memcached核心原理詳細剖析
memcached是什麼? 許多Web應用都將資料儲存到RDBMS中,應用伺服器從中讀取資料並在瀏覽器中顯示。 但隨著資料量的增大、訪問的集中,就會出現RDBMS的負擔加重、資料庫響應惡化、 網站顯示延遲等重大影響。 這時就該memcached
決策樹相關演算法——Bagging之基於CART的隨機森林詳細說明與實現
1 前言 1.1 本篇部落格主要記錄的是基於CART決策樹實現的隨機森林演算法,主要是從以下四個方面介紹: CART決策樹的構建思想;整合學習中的Bagging思想;基於CART決策樹的隨機森林程式碼實現;隨機森林不易過擬合的分析。(其中不易過擬合併不是說隨機