授人以鱼不如授人以渔,《三分钟理解Spring源码》专栏教你如何学习、思考、阅读Spring框架,并应对其它开源框架不再畏惧。
做Java开发的朋友基本都是每天接触Spring框架,说到Spring,我相信所有人张开就可以来,Spring不就是IOC,AOP嘛,我的大部分项目都是基于Spring开发的。对,没错,现在大家思考一下什么是IOC?什么又是AOP呢?如果看了这个提问后完全没有思路或者说的模糊不清的,恭喜你,这个文章非常适合你的,可以给你提供如何看源码的思路,并让你从源码级别了解Spring的内核。
1、什么是IOC
从我的理解来说来说 IOC分为依赖注入和控制反转两部分。
控制反转:在java编程中就是程序猿将 new 一个对象的权利交给了IOC容器。下面的代码是程序员手动new一个对象的过程。
static class A {
public void studyIoc() {
log.info("手把手教你深入理解Spring源码");
}
}
public static void main(String args[]) {
//硬编码 new A 对象
A a = new A();
a.studyIoc();
}
依赖注入:在java编程中一个对象内部的属性,一般都是通过构造方法注入、set注入。而Spring的IOC容器可以通过配置文件、@Autowire注解进行自动装配。 下面的代码是程序员手动通过构造方法注入一个对象的过程。
static class A {
public void studyIoc() {
log.info("手把手教你深入理解Spring源码");
}
}
static class B {
static A a;
public B(A a) {
this.a = a;
}
}
public static void main(String args[]) {
A a = new A();
// B对象 依赖 A对象,通过构造方法注入
new B(a);
}
看到上面两个解释,有没有突然很好奇IOC内部是如何处理控制反转和依赖注入的呢。下面我上一段简单的代码 1.0版本 超简易IOC容器,来给大家解惑Spring的IOC是如何实现的。
public class Ioc {
Map<String, Object> map = new HashMap<String, Object>();
public Object getBean(String beanName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String className = PropertiesUtil.getApplicationcontextProperties(beanName);
Class clazz = Class.forName(className);
return clazz.newInstance();
}
}
上面Ioc类就是一个简易版的IOC容器,有没有发现内部的数据结构其实就是一个Map,IOC容器这么羞射难懂的词,其实底层实现就是这么简单!通过调用getBean方法,利用反射可以获取容器中任意对象! 继续上代码
public class PropertiesUtil {
private static final MicroLogUtil log = MicroLogFactory.getLogger();
private static Properties applicationcontextProperties;
private static final String applicationcontextFileName = "applicationcontext.properties";
static {
applicationcontextProperties = new Properties();
try {
applicationcontextProperties.load(new ClassPathResource(applicationcontextFileName).getInputStream());
log.info("初始化pay.properties成功");
} catch (Exception e) {
log.info("PropertiesUtils初始化失败", e);
}
}
public static String getApplicationcontextProperties(String key) {
return applicationcontextProperties.getProperty(key);
}
}
上面代码是getBean方法中的:String className = PropertiesUtil.getApplicationcontextProperties(beanName); 其实就是将配置文件加载到内存中,已方便我们通过JavaBean来获取配置文件中的信息,你是不是想起来了Spring似乎也规范了一个配置文件,通过<Bean>标签定义Bean对象的。
接下来上我们的配置文件代码
哈哈,这就是我们规约的配置文件,右边就是全类名,类似于Spring <bean>标签中的 class, 反射通过全类名,将编译后的字节码文件加载到JVM中,在运行时期就可以获取类的信息,并操作类中的属性、方法。(不理解的同学可以先去学习一下反射)。
@Test
public void runMethod() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
((A) getBean("A")).studyIoc();
}
测试一下刚刚的代码。
惊喜不惊喜,意外不意外?我们通过自己写的getBean方法,获取到指定的对象,并执行方法成功。
有没有发现我们现在获取一个对象已经不需要通过 new 这个关键字,其实基础的 IOC 容器就是这么简单,Spring底层就是一个Map数据结构去维护的,当然Ioc容器还有很多高级特性,在接下来的文章中我们阅读完源码,会升级一个2.0版本IOC容器,实现依赖注入,和一些高级特性。
大家对本篇文章感兴趣的朋友可以加 Q群:837348118 一起讨论源码,面试题,算法,公司文化。