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 ...
随机推荐
- Linux网络服务10——远程访问及控制
Linux网络服务10--远程访问及控制 一.SSH概述 1.SSH简介 SSH(Secure Shell)是一种安全通道协议,主要用来实现字符界面的远程登录.远程复制等功能.SSH协议对通信双方的数 ...
- 10分钟就能学会的.NET Core配置
.NET Core为我们提供了一套用于配置的API,它为程序提供了运行时从文件.命令行参数.环境变量等读取配置的方法.配置都是键值对的形式,并且支持嵌套,.NET Core还内建了从配置反序列化为PO ...
- touchmover手机移动端的拖动
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name= ...
- 从栈不平衡问题 理解 calling convention
最近在开发的过程中遇到了几个很诡异的问题,造成了栈不平衡从而导致程序崩溃. 经过几经排查发现是和调用规约(calling convention)相关的问题,特此分享出来. 首先,讲一下什么是调用规约. ...
- web前端2017.6.10
表单元素:用于客户端和服务端进行信息交互的通道 <form></form>:所有的表单元素都应该放在里面 文本输入框:<input type="text&quo ...
- dynamic-load-apk 插件与宿主方法互调
新建项目 DlPluginHost,下载dynamic-load-apk源码 1.将dynamic-load-apk 文件夹中的lib做为module导入到DlPlginHost 2.导入到Plugi ...
- JAVA - 深入JAVA 虚拟机 3
类的初始化时机 package practise; class Parent{ static int a =3; static{ System.out.println("Parent sta ...
- voa 2015 / 4 / 13
couch potato : someone who likes to spend a lot of time sitting or lying down while watching televis ...
- es6的一些个人总结
es6的一些知识点 前言:es6(ECMAscript2015)标准 let.const.var的一些区别 let.const 块级作用域.全局作用域.函数作用域 var 全局作用域.函数作用域 变量 ...
- jsonp的原理和实现
什么是JSONP? javascript高级程序设计中是这样介绍jsonp的: jsonp是JSON with padding(填充式JSON或参数式JSON )的简写,是应用JSON的一种新方法,在 ...