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的更多相关文章
- Spring事务源码阅读笔记
1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...
- spring framework 源码
spring framework 各版本源码下载地址 现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-pro ...
- Idea搭建spring framework源码环境
spring的源码目前放在github上,https://github.com/spring-projects/spring-framework 一.安装Git 二.安装Gradle gradle为解 ...
- Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)
去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...
- Spring JdbcTemplate源码阅读报告
写在前面 spring一直以删繁就简为主旨,所以设计出非常流行的bean管理模式,简化了开发中的Bean的管理,少写了很多重复代码.而JdbcTemplate的设计更令人赞叹,轻量级,可做ORM也可如 ...
- 【面试】足够应付面试的Spring事务源码阅读梳理(建议珍藏)
Starting from a joke 问:把大象放冰箱里,分几步? 答:三步啊,第一.把冰箱门打开,第二.把大象放进去,第三.把冰箱门带上. 问:实现Spring事务,分几步? 答:三步啊,第一. ...
- Spring,tk-mapper源码阅读
Mybatis的源码学习(一): 前言: 结合spring本次学习会先从spring-mybatis开始分析 在学习mybatis之前,应该要对spring的bean有所了解,本文略过 先贴一下myb ...
- Spring Framework 源码编译导入
预先准备环境 Window 10 JDK环境 List item Gradle 以及其环境变量配置 spring-framework源码(https://gitee.com/mirrors/Sprin ...
- Robot Framework 源码阅读 day2 TestSuitBuilder
接上一篇 day1 run.py 发现build test suit还挺复杂的, 先从官网API找到了一些资料,可以看出这是robotframework进行组织 测试案例实现的重要步骤, 将传入的te ...
随机推荐
- 常见web容器
当前主流的还是tomcat,jetty有较大的潜力,缩小彼此间差距,
- golang 浮点数 取精度的效率对比
需求 浮点数取2位精度输出 实现 代码 package main import ( "time" "log" "strconv" " ...
- 实现Runnable接口和继承Thread类之间的区别
在Java语言中,我们都知道,有两种创建线程的方式,一中是使用Runnable接口,另一种是使用Thread类. public class DemoRunnable implements Runnab ...
- 浅析TCP/IP 协议
TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族. TCP/IP协议模块关系 从协议分层模型方面来讲,TCP/IP由四个层次组成:网络接口层.网络层.传输层.应用层 ...
- “前”方有坑,绕道而行(一)-- H5+CSS
1. 关于 数字.英文 不换行问题: 情景:昨天测试 小程序,输入英文,没有换行,且 下方有横向滚动条: 解决:word-break: word-break:break-all; /*只对英文起作用 ...
- 浅谈Swift和OC的区别
前言 转眼Swift3都出来快一年了,从OC到Swift也经历了很多,所以对两者的一些使用区别也总结了一点,暂且记录下,权当自己的一个笔记. 当然其中一些区别可能大家都有耳闻,所以这里也会结合自身的一 ...
- docker 架构
看别的地方大致介绍的,粘贴过来 Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器. Docker 容器通过 Docker 镜像来创建. 容器与镜像的关 ...
- 通过bin-log对mysql进行数据恢复
mysqlbinlog --database=数据库名 --start-date="2017-06-01 5:00:00" --stop-date="2017-06-1 ...
- 并发编程(四):ThreadLocal从源码分析总结到内存泄漏
一.目录 1.ThreadLocal是什么?有什么用? 2.ThreadLocal源码简要总结? 3.ThreadLocal为什么会导致内存泄漏? 二.ThreadLoc ...
- Linux编程之epoll
现在有这么一个场景:我是一个很忙的大老板,我有100个手机,手机来信息了,我的秘书就会告诉我"老板,你的手机来信息了."我很生气,我的秘书就是这样子,每次手机来信息就只告诉我来信息 ...