spring是个顶级的框架,这话没毛病。很多人想把它征服,想去阅读它的源码,弄懂它的设计思想,从中学到精粹。
但是很多次打开后,看到庞大的体系结构,就懵逼了,不知从何入手。
我在这里总结下学习spring的切入点:
IOC
控制反转,是spring的核心吧,对于bean的生面周期的管理。AOP
面向切面编程,基于JDK动态代理和cglib字节码实现。
首先从IOC开始吧,控制反转,就是将对象的创建转移给框架,不需要你去new,你只需要通过配置或者注解来让它知道从哪入手。这样做有什么好处?
- 不用再编写创建对象的代码和维持其复杂的依赖关系。
- 定义一个接口,可以方便更改其实现类,或者注入需要的属性。
然后就是自己写个简单的接口和实现,开始debug,通过xml配置的方式来注入bean:
<bean id="test" class="com.fcs.xmls.TestBean">
<!-- 配置属性phone -->
<property name="phone" value="15507516532"></property>
<!-- 配置属性age,虽然此处是字符串“25”,但是Spring会识别age的类型,然后把字符串“14”转变后赋值给age -->
<property name="age" value="25"></property>
</bean>
用下面的方式获取bean:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
TestBean t = (TestBean) ac.getBean("test");
用idea弄个类继承关系图:
可以看到BeanFactory,从命名可以看出来这是个工厂模式,所以从这里你需要了解工厂模式(工厂方法模式)。
在跟踪的过程中,很容易就跳到了AbstractApplicationContext 中的refresh 方法,在这个方法做了一系列操作:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
同样,用注解来一波:
@Component
public class MessagePrinter {
final private MessageService service;
@Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(this.service.getMessage());
}
}
ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
MessagePrinter printer = context.getBean(MessagePrinter.class);
也可得到下图:
两者的上层结构基本相同,分离点也在AbstractApplicationContext ,各自有了不同的扩展。所以重点还是在AbstractApplicationContext 的refresh 方法。
这里可以看到第二个模式:模板方法模式。在AbstractApplicationContext 中定义算法簇,子类做不同的具体实现。
这就是切入点了。只是简单的分析下,细节还得去看,如果看不下去,还得学习设计模式。此外思想可以参考spring-tiny,一个简单的ioc容器实现。