1. 程式人生 > >Spring-Framework 原始碼閱讀之AnnotationBeanUtils

Spring-Framework 原始碼閱讀之AnnotationBeanUtils

  Java程式設計師,就是要學會一個名字叫做“春”的東西,這玩意運用的非常的廣泛,現在如果你的業務系統或者軟體沒有在這個東西上開發,都不要意思拿出來。因為你更不上時代了。在平時的工作的中基本都是簡單的運用,沒有深入的瞭解內部的肌理。這次我一定可以滿滿的看完裡面的骨架。加油!加油!加油!

  在之前我也看過一些講Spring的書籍,比如<<Spring揭祕>>,《Spring技術內幕》。大體知道了Spring的工作流程,但是還是有些迷茫。有一點一知半解的感覺。接下來我準備以自己一知半解的半桶水的知識去閱讀Spring的原始碼。根據自己的模模糊糊的感覺和去網上搜索來幫助閱讀。這一次要地毯式的搜尋閱讀。可是有時也會覺得Spring 框架這麼大,如此的閱讀是不是浪費時間。但是又有另一種想法,只要我們把每個類的作用都瞭解清楚了,每個類都自己寫一下單元測試。都跟進原始碼閱讀。這樣等我大部分的內容都閱讀了,Spring的瞭解深度會更加清晰咯。

  首先第一步就是下載Spring原始碼,然後匯入Idea中,如下圖所示。

  Spring 最最最核心的地方就是Bean,所以我準備從spring-beans這個工程看起。首先第一個package: org.springframework.beans.annotation,這個包下就只有一個類AnnotationBeanUtils,該類就只有一個核心的方法,就是拷貝註解值到指定的類中。

public abstract class AnnotationBeanUtils {

    /**
     * Copy the properties of the supplied {@link
Annotation} to the supplied target bean. * Any properties defined in {@code excludedProperties} will not be copied. * @param ann the annotation to copy from * @param bean the bean instance to copy to * @param excludedProperties the names of excluded properties, if any * @see
org.springframework.beans.BeanWrapper */ public static void copyPropertiesToBean(Annotation ann, Object bean, String... excludedProperties) { copyPropertiesToBean(ann, bean, null, excludedProperties); } /** * Copy the properties of the supplied {@link Annotation} to the supplied target bean. * Any properties defined in {@code excludedProperties} will not be copied. * <p>A specified value resolver may resolve placeholders in property values, for example. * @param ann the annotation to copy from * @param bean the bean instance to copy to * @param valueResolver a resolve to post-process String property values (may be {@code null}) * @param excludedProperties the names of excluded properties, if any * @see org.springframework.beans.BeanWrapper */ public static void copyPropertiesToBean(Annotation ann, Object bean, @Nullable StringValueResolver valueResolver, String... excludedProperties) { Set<String> excluded = new HashSet<>(Arrays.asList(excludedProperties)); Method[] annotationProperties = ann.annotationType().getDeclaredMethods(); //獲取註解上的方法 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean); //同過bean物件獲取bean的定義BeanDefinition for (Method annotationProperty : annotationProperties) { //遍歷方法 String propertyName = annotationProperty.getName(); //獲取方法名 if (!excluded.contains(propertyName) && bw.isWritableProperty(propertyName)) { Object value = ReflectionUtils.invokeMethod(annotationProperty, ann); //獲取註解方法上的值 if (valueResolver != null && value instanceof String) { value = valueResolver.resolveStringValue((String) value); //處理value的值,StringValueResolver的作用比如處理佔位符${} } bw.setPropertyValue(propertyName, value);//把該值設定到bean定義上。 } } } }

從上面的解釋,應該非常清楚該工具類的作用,現在我們來寫一個例子來驗證。

package com.qee.beans.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FooAnnotation {
    String name();

    int age();
}
package com.qee.beans.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Foo2Annotation {
    String accountId();
}
package com.qee.beans.annotation;


@FooAnnotation(name = "xiao ming", age = 23)
public class Foo {
    private String names;

    private int age;

    @Foo2Annotation(accountId = "123456")
    private  String id;

    public String getNames() {
        return names;
    }

    public void setName(String names) {
        this.names = names;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void  setAccountId(String id){
        setId(id);
    }
}
package com.qee.beans.annotation;

import org.springframework.beans.annotation.AnnotationBeanUtils;


public class AnnotationBeanUtilsTest {
    public static void main(String[] args) throws NoSuchFieldException {
        testCopyProperties();
        testCopyProperties2();
        testCopyPropertiesWithIgnore();
    }

    public static void testCopyProperties2() throws NoSuchFieldException {

        Foo2Annotation annotation = Foo.class.getDeclaredField("id").getAnnotation(Foo2Annotation.class);
        Foo foo = new Foo();
        AnnotationBeanUtils.copyPropertiesToBean(annotation, foo);
        System.out.println(foo.getId());

    }

    public static void testCopyProperties() {
        FooAnnotation annotation = Foo.class.getAnnotation(FooAnnotation.class);
        Foo foo = new Foo();
        AnnotationBeanUtils.copyPropertiesToBean(annotation, foo);
        System.out.println("Name  :  " + annotation.name() + "  " + foo.getNames());
        System.out.println("Age   :   " + annotation.age() + "  " + foo.getAge());
    }

    public static void testCopyPropertiesWithIgnore() {
        FooAnnotation annotation = Foo.class.getAnnotation(FooAnnotation.class);
        Foo foo = new Foo();
        foo.setName("Juergen Hoeller");
        foo.setAge(30);
        AnnotationBeanUtils.copyPropertiesToBean(annotation, foo, "name", "age");
        System.out.println("Name  :  " + annotation.name() + "  " + foo.getNames());
        System.out.println("Age   :   " + annotation.age() + "  " + foo.getAge());
    }

}

  從上面測試例子可以知道,AnnotationBeanUtils.copyPropertiesToBean把註解上的值拷貝給某個物件,只有某個物件有這個註解方法的setXX方法。並且如果該物件的某個屬性已經有值了,就不會在拷貝註解上的值到該屬性上。

  從上面AnnotationBeanUtils的原始碼上,我們知道引入了新的Spring物件--StringValueResolver,BeanWrapper,ReflectionUtils。在之後的原始碼閱讀中,在進行解析。在這裡做一下紅色標記,哇哈哈,哇哈哈,哇哈哈!!!!!!

待看的,等看看到這些包的時候,在繼續分析下面的內容

org.springframework.util.StringValueResolver

org.springframework.beans.BeanWrapper

org.springframework.util.ReflectionUtils

相關推薦

Spring-Framework 原始碼閱讀AnnotationBeanUtils

  Java程式設計師,就是要學會一個名字叫做“春”的東西,這玩意運用的非常的廣泛,現在如果你的業務系統或者軟體沒有在這個東西上開發,都不要意思拿出來。因為你更不上時代了。在平時的工作的中基本都是簡單的運用,沒有深入的瞭解內部的肌理。這次我一定可以滿滿的看完裡面的骨架。加油!加油!加油!   在之前我也看過一

Spring-Framework 原始碼閱讀@Autowired和AutowiredAnnotationBeanPostProcessor

  今天接下去講我們的內容,上次的解析了AnnotationBeanUtils這個類的運用和原始碼。今天主要關注的是Autowired和 AutowiredAnnotationBeanPostProcessor這2個類。首先我們來看一下Autowired標籤的定義。 @Target({ElementType

Spring-Framework 源碼閱讀AnnotationBeanUtils

哈哈 dex hold object pla efi str method 一點   Java程序員,就是要學會一個名字叫做“春”的東西,這玩意運用的非常的廣泛,現在如果你的業務系統或者軟件沒有在這個東西上開發,都不要意思拿出來。因為你更不上時代了。在平時的工作的中基本都是

Spring原始碼閱讀Bean載入(xml)1

先上兩張圖,簡單的畫了一下beanFactory各個類之間的關係,XmlBeanFactory是bean載入的入口和核心。Spring中大量使用了設計模式和UML中的設計原則,比如單一職責原則,從類圖可以看出,BeanFactory派生的各個介面,根據名字的不同,都增加了

Robot Framework 原始碼閱讀筆記

上次走到了具體測試執行的地方,感覺缺乏一個全域性觀,有點走不下去。 還是再回頭看看整個設計思路,所有的模組文件都可以從這裡訪問到: 使用文件: http://robotframework.org/robotframework/ 介面文件: http://robot-fra

Spring 原始碼閱讀 深入理解 finishBeanFactoryInitialization

原始碼入口 上篇博文中我們看到了將Spring環境中的 BeanPostProcessor找出來,新增到BeanFactory中的beanPostProcessors中,統一維護,本片博文繼續往下拓展,看下Spring如何例項化bean,以及如何實現在bean的例項化通過各種各樣的後置處理器完成bean的增強

Spring源碼閱讀Springs-beans(一)容器的基本實現

beans 閱讀 gin com -i add wid ans lock 一、Spring-beans Spring源碼閱讀之Springs-beans(一)容器的基本實現

Promise原始碼閱讀建構函式+then過程

前言 Promise是非同步程式設計的一種方案,ES6規範中將其寫入規範標準中,統一了用法。 考慮到瀏覽器的相容性,Vue專案中使用promise,就具體閱讀promise原始碼,看看內部的具體實現。 具體分析 通過具體例項來閱讀promise原始碼的實現,例項如下: new

Spring-web原始碼解析Filter-OncePerRequestFilter

轉自:  http://blog.csdn.net/ktlifeng/article/details/50630934 基於4.1.7.RELEASE 我們先看一個filter-mapping的配置 

Netty 原始碼閱讀初始環境搭建

推薦 netty 系列原始碼解析合集 http://www.iocoder.cn/Netty/Netty-collection/?aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3R6c18xMDQxMjE4MTI5L2FydGljbGUvZGV0YWlscy83OD

jdk原始碼閱讀——arraylist

首先看一下他的建構函式: public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } 其實arraylist還有其他的建構函式,可以指定陣列的長度,這裡先從最基本的入

netty原始碼閱讀效能優化工具類Recycle異執行緒獲取物件

在這篇《netty原始碼閱讀之效能優化工具類之Recycler獲取物件》文章裡面,我們還有一個scavenge()方法沒有解析,也就是在別的執行緒裡面回收物件。下面我們開始介紹,從這個方法開始進入: boolean scavenge() { // con

Spring文件閱讀AOP

Aspect-oriented Programming (AOP) 補充了Object-oriented Programming (OOP)。OOP最重要的概念模組是類(class),而AOP中則是切面。AOP可以在多種型別和多個類間進行操作,可以認為AOP串起了這些資料。OOP使用封裝,繼承和多型來定義物件

我的原始碼閱讀路:redux原始碼剖析

前言 用過react的小夥伴對redux其實並不陌生,基本大多數的React應用用到它。一般大家用redux的時候基本都不會單獨去使用它,而是配合react-redux一起去使用。剛學習redux的時候很容易弄混淆redux和react-redux,以為他倆是同一個

Spring Ioc 原始碼分析Bean的載入和構造

我們都知道,Spring Ioc和Aop是Spring的核心的功能,因此花一點時間去研究還是很有意義的,如果僅僅是知其所以然,也就體會不到大師設計Spring的精華,還記得那句話,Spring為JavaEE開發帶來了春天。IOC就是Inversion of control 也就是控制反轉的意思,另一種稱呼叫做

netty原始碼閱讀解碼值基於固定長度解碼器分析

固定長度解碼器FixedLengthFrameDecoder比較簡單,我們看下它類的註釋: /** * A decoder that splits the received {@link ByteBuf}s by the fixed number * of bytes.

netty原始碼閱讀解碼基於長度域解碼器引數分析

這篇文章我們放鬆一點,只分析基於長度域解碼器的幾個引數, lengthFieldOffset :長度域的偏移量,也就是長度域要從什麼地方開始 lengthFieldLength:長度域的長度,也就是長度域佔多少個位元組 lengthAdjustment:長度域的值的調整

Spring Cloud原始碼分析Eureka篇第六章:服務註冊

在文章《Spring Cloud原始碼分析之Eureka篇第四章:服務註冊是如何發起的 》的分析中,我們知道了作為Eureka Client的應用啟動時,在com.netflix.discovery.DiscoveryClient類的initScheduledT

netty原始碼閱讀解碼基於長度域解碼器分析

基於長度域解碼器LengthFieldBasedFrameDecoder我們主要分析以下三點: 1、計算需要抽取的資料包的長度 2、跳過位元組邏輯處理 3、丟棄模式下的處理 首先原始碼還是LengthFieldBasedFrameDecoder的decode方法:

netty原始碼閱讀編碼MessageToByteEncoder

MessageToByteEncoder的write過程,我們分析以下幾步: 1、匹配物件 2、分配記憶體 3、編碼實現 4、釋放物件 5、傳播資料 6、釋放記憶體 原始碼在這裡: @Override public void write(Cha