有人说JAVA企业级应用没啥技术含量,玩不了大数据的技术人员是很杯具的存在。大部分生命的时间是处理复杂的业务,沉迷于一堆框架和API的应用,却没有足够的能力去解决计算机世界里面高深的问题。
也有一些人说,这个是社会分工.一些底层开发人员开发出牛逼的操作系统,语言,框架和库。一些上层开发人员利用这些工具开发出软件来,着实解决人们碰到的问题。两种人员都很需要。
这个让我想到以前看到的“降级论”,现在也有一部分开发人员从码农变成果农。这时常能让我想起一个问题:活着是为了什么。好了,偏题太远,回归正题。
Spring Framework(下文简称为Spring)提供了很多功能,使得很多简单的应用开发,尤其是一些政府,小企业应用,变成Action->Service->DAO+一堆Interface(我讨厌很多莫名其妙的接口),just make skins for dababase.
当然,Spring 的框架实现还是很强大的,虽然里面没啥高深算法,但是的确使开发工作简便了不少(Joel曾说,OOP太简单了,不足以分辨出优秀的程序员… )。但是,对一个对未知事物充满好奇心的人来说,理解Spring的内部实现还是很有必要的。
本文主要分为2个章节,分别是IOC实现原理,AOP实现原理
注:本文不会太多涉及Spring Framework 源码内部实现框架细节,细节部分请阅读本文最后的参考章节。
====
对象之间的依赖关系本来应该是直接是通过在代码中,A类直接创建另外一个B类的实例,结果变成是在IOC容器中,通过配置文件来配置对象依赖关系。至于为什么需要IOC,网上的说法是主要是因为复杂对象之间的依赖关系通过IOC管理起来比较简单,不需要手写大量代码。
其实,我更喜欢这几个理由,比如说
====
我们需要配置文件来保存对象的依赖关系。
既然说到配置文件,那么就必须涉及到配置文件的解析,解析前需要校验文件合法性,解析后的内容再与相应的java类映射。
但是在开始解析文件之前,首先要搞清楚2个问题:
搞清楚上述问题后,我们再进行选择解析组件。就XML而言,简单的文件直接通过JAXB/Digester来解决;复杂的一般是使用SAX来解决,例如Spring和Activiti。
====
回到正题,从spring的单元测试中,找到这段代码: void org.springframework.beans.factory.xml.XmlBeanFactoryTests.testInitMethodIsInvoked() throws Exception
@Test
public void testInitMethodIsInvoked() throws Exception {
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(xbf).loadBeanDefinitions(INITIALIZERS_CONTEXT);
DoubleInitializer in = (DoubleInitializer) xbf.getBean("init-method1");
// Initializer should have doubled value
assertEquals(14, in.getNum());
}
执行核心时序如下:
====
在单元测试中void org.springframework.context.support.ClassPathXmlApplicationContextTests.testSingleConfigLocation()
,我们找到这段话
@Test
public void testSingleConfigLocation() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(FQ_SIMPLE_CONTEXT);
assertTrue(ctx.containsBean("someMessageSource"));
ctx.close();
}
执行核心时序如下:
====
AOP完成了初学者一些看起来很神奇的功能,其实底层都是通过字节码增强的方式来透明地完成了一些Magic.AOP过于强大,以至于常有一些不适合的场景,比如用AOP进行打日志
阅读本章之前需要了解一下几个概念:静态代理,JDK动态代理,字节码增强动态代理
====
配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="human" class="com.vavi.proxy.Person">
</bean>
<bean id="sleepHelper" class="com.vavi.spring.aop.jdk.SleepAdvice">
</bean>
<bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep" />
</bean>
<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="sleepHelper" />
<property name="pointcut" ref="sleepPointcut" />
</bean>
<bean id="humanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="human" />
<property name="interceptorNames" value="sleepHelperAdvisor" />
<property name="proxyInterfaces" value="com.vavi.proxy.Sleepable" />
</bean>
</beans>
测试类代码如下:
public class SpringProxyTest {
public static void main(String[] args) {
ApplicationContext appCtx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Sleepable sleeper = (Sleepable) appCtx.getBean("humanProxy");
sleeper.sleep();
}
}
====
====
=====
Why need IOC
Spring 框架的设计理念与设计模式分析
Spring 技术内幕