端午特别篇(二)-Spring源码解读
警告:今天的内容可能会使您感到不适!!!
前景引入:
从线下课开始到现在,常常会听到老师说一句话,Ctrl点击去一下。一般我们会得到一个我们自己写的方法。但是,如果点的是环境提供(JDK)的方法呢,再点进去之后是啥样呢(debug时也会遇见),在文件的导航栏看到的是一个.class的文件,下面是一段java代码。到这里很多同学的Eclipse就查看不到了。于是问老师,老师这边呢,给出了一个这样的说法:我的Eclipse带反编译,你需要反编译环境才可以看到。
最近在讲到Spring时也会提到,这是底层实现的,有兴趣的同学可以去看下。
到这里,引入了两个关键词,反编译,底层。那么这到底是什么东西呢?对于我们以后的发展,及对问题的解决是否会提供思路呢?答案是肯定的。
一.源代码与反编译
1.1 源代码
在我们学习Java前,还学过C语言,更底层一点是汇编语言,最后是0101这些二进制。
通过OD对Tim进行反编译,主要内容为汇编语言
其实Java就是一部分汇编,一部分C/C++编写的。那么他们可以叫做java的源代码。而在刚入门开发中,了解到.class就ok。
1.2 反编译及工具推荐
想要看到.class文件,必须有反编译工具,JD-GUI。然后是api,doc文档。
个人感觉使用IDEA看着更方面一些,而且用到啥就自动下载啥。
二.源码解读
2.1 如何正确阅读
老师在讲Sring课的时候,源码部分都是一带而过。如果只是跟老师的讲课节奏遇到一个看一个,对于源码的掌握就比较缓慢。正确是应该有一个脉络,一个体系,把他们串起来。先从Spring的结构出发,然后在细化到每个具体的方法,最后再去看细节。然后记录思维导图/流程图
2.2 Spring源码入门
知道了如何认识源代码之后,就需要我们找到一个切入点来进行来学习。以最近项目举例,测试的时候经常使用的这条语句。
ApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");
在这里下一个断点,然后跟踪,之后我们便可以得到一个简略的Spring架构图
为了简化步骤,再分析的时候可以看AbstractApplicationContext中的refresh()方法
架构解读:
左边开始,是注入的一些信息,我们目前用到的是xml配置和annotation(注解)。有了配置信息,那么一下步理应是生成bean。但事实上需要对不同的定义形式进行统一封装。这里用到了一个BeanDefinitionReader。
下一步交给到了BeanDefition,不过在通过定义创建对象(实例化)之前,还需要走BeanFactory的反射。
由于基础反射的课程本班并没有讲解,所以大家对这块比较陌生。下面用一个反射+自定义注解(非Spring的自动装配)实现一下注解如何如何生成对象。
public class Test2 {public static void main(String[] args) {UserController userController = new UserController();class<? extends UserController> clazz = userController.getClass();//获取当前controller的属性有哪些Stream.of(clazz.getDeclaredFields()).forEach(field ->{//判断一个属性值是否使用了@Autowired修饰AutoWired annotation = field.getAnnotation(AutoWired.class);if (annotation!=null){field.setAccessiable(true);//获取到属性类型,方便创建对象Class<?> type = field.getType();//创建具体对象Object o = null;try {o = type.newInstance();field.set(userController, 0);}catch (InstantiationException e){e.printStackTrace();}catch (IllegalAccessException e){e.printStackTrace();}}});System.out.println(userController.getUserService());}}
接下来到了Bean的生命周期,在老师所讲的步骤外,多了一点东西,比如最开始的Aware接口是做什么用的,初始化之前、初始化之执行的又是什么?FactoryBean又是什么?
2.3 Spring的其他方法解析
FactoryBean
*** Interface to be implemented by objects used within a {@link BeanFactory} which* are themselves factories for individual objects. If a bean implements this* interface, it is used as a factory for an object to expose, not directly as a* bean instance that will be exposed itself.** <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>* A FactoryBean is defined in a bean style, but the object exposed for bean* references ({@link #getObject()}) is always the object that it creates.** <p>FactoryBeans can support singletons and prototypes, and can either create* objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}* interface allows for exposing more fine-grained behavioral metadata.** <p>This interface is heavily used within the framework itself, for example for* the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the* {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for* custom components as well; however, this is only common for infrastructure code.** <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not* supposed to rely on annotation-driven injection or other reflective facilities.</b>* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in* the bootstrap process, even ahead of any post-processor setup. If you need access* other beans, implement {@link BeanFactoryAware} and obtain them programmatically.** <p>Finally, FactoryBean objects participate in the containing BeanFactory's* synchronization of bean creation. There is usually no need for internal* synchronization other than for purposes of lazy initialization within the* FactoryBean itself (or the like).** @author Rod Johnson* @author Juergen Hoeller* @since 08.03.2003* @param <T> the bean type* @see org.springframework.beans.factory.BeanFactory* @see org.springframework.aop.framework.ProxyFactoryBean* @see org.springframework.jndi.JndiObjectFactoryBean*/public interface FactoryBean<T> {
FactoryBean的三个方法
//返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。T getObject() throws Exception;//返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。Class<?> getObjectType();//返回FactoryBean创建的bean类型。default boolean isSingleton() {return true;}
总结出来一句话:生产唯一特殊复杂对象。
BeanFactoryPostProcessor与BeanPostProcesser
如果我们想对bean对象进行二次加工,那么就会用到这些增强器。也就是最近在学的advice(通知/增强)。详细请参照昨天的内容。
三.总结
上述是个人在源码阶段所认识的内容,由于能力有限,没有深入了解(监听器都没有提到),但对于Spring的认识具有了一定的提升。在对spring的开发有一定经验后可以继续提升。下面附一张SpringBoot2.2.2的启动图供以后学习。
