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的更多相关文章

  1. Spring事务源码阅读笔记

    1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...

  2. spring framework 源码

    spring framework 各版本源码下载地址 现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-pro ...

  3. Idea搭建spring framework源码环境

    spring的源码目前放在github上,https://github.com/spring-projects/spring-framework 一.安装Git 二.安装Gradle gradle为解 ...

  4. Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)

    去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...

  5. Spring JdbcTemplate源码阅读报告

    写在前面 spring一直以删繁就简为主旨,所以设计出非常流行的bean管理模式,简化了开发中的Bean的管理,少写了很多重复代码.而JdbcTemplate的设计更令人赞叹,轻量级,可做ORM也可如 ...

  6. 【面试】足够应付面试的Spring事务源码阅读梳理(建议珍藏)

    Starting from a joke 问:把大象放冰箱里,分几步? 答:三步啊,第一.把冰箱门打开,第二.把大象放进去,第三.把冰箱门带上. 问:实现Spring事务,分几步? 答:三步啊,第一. ...

  7. Spring,tk-mapper源码阅读

    Mybatis的源码学习(一): 前言: 结合spring本次学习会先从spring-mybatis开始分析 在学习mybatis之前,应该要对spring的bean有所了解,本文略过 先贴一下myb ...

  8. Spring Framework 源码编译导入

    预先准备环境 Window 10 JDK环境 List item Gradle 以及其环境变量配置 spring-framework源码(https://gitee.com/mirrors/Sprin ...

  9. Robot Framework 源码阅读 day2 TestSuitBuilder

    接上一篇 day1 run.py 发现build test suit还挺复杂的, 先从官网API找到了一些资料,可以看出这是robotframework进行组织 测试案例实现的重要步骤, 将传入的te ...

随机推荐

  1. WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)

    到现在为止,我们创建了一个简单的MVVM的例子,包含了实现了的属性和命令.我们现在有这样一个包含了例如textbox类似的输入元素的视图,textbox用绑定来和view model联系,像点击but ...

  2. eclipse 下,使用正常模式可以运行,DEBUG模式就卡住的解决方案

    最近开发的时候遇到一个问题,就是用运行就可以编译整个项目,但是使用debug模式就卡住了,编译一部分就不动了.开始我以为是项目太大的关系 但是也不至于就DEBUG不行,所以网上差了些资料,原来是DEB ...

  3. nodejs构建多房间简易聊天室

    1.前端界面代码 前端不是重点,够用就行,下面是前端界面,具体代码可到github下载. 2.服务器端搭建 本服务器需要提供两个功能:http服务和websocket服务,由于node的事件驱动机制, ...

  4. Linux命令 文件的建立移动删除

    cat [功能说明] 建立文件  #cat命令用来串接文件或显示文件内容的但是如果从标准输入设备中读入数据并将结果重定向到一个新的文件中,则可以到达建立新文件的目的.Cat命令只能在编辑新的文件时只能 ...

  5. qt中setStyleSheet导致的内存泄漏

    原始日期: 2017-01-05 19:31 现象:程序运行至某一个界面下,内存出现缓慢持续的占用内存增长   原因:经过排查,确定是在事件派发的槽函数中频繁重复调用setStyleSheet导致的 ...

  6. dubbo与zookeeper的关系

    Dubbo建议使用Zookeeper作为服务的注册中心. 1.   Zookeeper的作用: zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是 ...

  7. scanner--inputstreamreader--console对比

    1 JDK 1.4 及以下版本读取的方法 JDK 1.4 及以下的版本中要想从控制台中输入数据只有一种办法,即使用System.in获得系统的输入流,再桥接至字符流从字符流中读入数据.示例代码如下: ...

  8. CentOS yum 安装 PHP 5.6.24

    配置yum源 追加CentOS 6.5的epel及remi源. # rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel- ...

  9. linux服务器load的含义

    Linux的Load(系统负载),是一个让新手不太容易了解的概念.load的就是一定时间内计算机有多少个active_tasks,也就是说是计算机的任务执行队列的长度,cpu计算的队列. top/up ...

  10. 原生js表单序列化----- FormData

    <style type="text/css"> .progress{ height: 10px; width: 600px; border: 1px solid red ...