书籍: Spring in action 第四版及源码,,,spring 源码深度解析(郝佳)
ClassPathXmlApplicationContext context =
ClassPathXmlApplicationContext(
);
从上面这句调试进入,Spring的源码:
构造函数中,将文件的位置存放到
setConfigLocations(configLocations);
if (refresh) { //这个变量默认为 true
refresh();
}
refresh()这个函数,做了很多事情,依次为:
(.) {
prepareRefresh(); // 这个方法里面处理了properties文件
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 将 this.beanFactory 初始化 为 DefaultListableBeanFactory,这个类很核心。
// 里面有个关键的方法 loadBeanDefinitions(beanFactory); 将所有的BeanDefinition加载到beanFactory
//里面设置了beanFactory的ClassLoader,BeanExpressionResolver等等
//还可能注册几个特殊的bean,比如envirment,systemProperties等等
prepareBeanFactory(beanFactory);
{
//这是beanFactory的后处理器,这里可以修改beanDefinition的信息
postProcessBeanFactory(beanFactory);
//这里是调用了beanFactory的后处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册bean的后处理器
registerBeanPostProcessors(beanFactory);
//初始化国际化信息
initMessageSource();
//事件广播器的初始化
initApplicationEventMulticaster();
//Initialize other special beans in specific context subclasses.
onRefresh();
//注册事件的监听者
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//实例化所有的非延迟加载的单例bean, 会遍历bd的列表,如果是singleton,就会继续往下走
//很深的地方有个doGetBean方法,再进去里面很多前后处理和检查,然后
// singletonObject = singletonFactory.getObject(); 把当前这个name的bean实例化,这里面也会同时加载那些需要依赖的bean
// 最后 addSingleton(beanName, singletonObject);把实例化的bean 加入到了缓存里面
// 当我们获取这个bean的时候,就会从缓存里面读取
finishBeanFactoryInitialization(beanFactory);
//发布完成事件,注册一个lifecycleProcessor
finishRefresh();
}
(BeansException ex) {
.warn(, ex);
destroyBeans();
cancelRefresh(ex);
ex;
}
}
AbstractXmlApplicationContext的loadBeanDefinitions方法,处理将xml配置的bean转化为BeanDefinition
DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions
这个对象是reader对象是被ApplicationContext对象所持有
很深的地方,有个parseBeanDefinitions 这个方法,把xml的节点传进入,并进行解析,最后加入到一个delegate对象上,这个对象的类型是 BeanDefinitionParseDelegate.
1 .这个地方,会区分是默认的Bean,import等等节点,还是Aspect等等其他custom节点,会做不同的解析。
最后,将ConfigurableListableBeanFactory将BeanDefinition注册到自己的缓冲中,beanDefinitionNames和
beanDefinitionMap.
2. NamespaceHandler (org.springframework.beans.factory.xml) 定制化的节点的handle,比如AopNamespaceHandler (org.springframework.aop.config) 这个是处理 aop的。
CacheNamespaceHandler (org.springframework.cache.config)
有这样一个类 ConfigBeanDefinitionParser (org.springframework.aop.config) , 对aop下面的节点做了解析。
通常在aop被解析以后会有以下的一些类,被注册到BeanDefinitionMap中,将实现以后的Aop做准备。
[org.springframework.aop.aspectj.AspectJExpressionPointcut] 表达式切点 [org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator] 这个类建立代理的创建者[org.springframework.aop.aspectj.AspectJPointcutAdvisor] 切点顾问 如before, after, around等五种类型
3。下面来看看,aop在bean实例化的时候,如何被代理实现的。
AbstractBeanFactory 一般这个类实现了Bean的实例化
在上面说的doGetBean方法进去,
AbstractAutowireCapableBeanFactory 这个类里面
最后,这个对象的doCreateBean方法返回了一个AspectJAwareAdvisorAutoProxyCreator的实例。
AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation) 这个类及其父类,实现了查找advices和wrap bean的工作
getAdvicesAndAdvisorsForBean 这里会查找到相关的AspectJPointcutAdvisor对象,每个advisor持有一个advice. 比如,before,around等等advice.
AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法进去,就是
bean的后处理,最后到ProxyCreator的wrapIfNecessary去包装了bean实例。
最终AbstractAutoProxyCreator的createProxy方法,包装bean实例。
org.springframework.aop.framework.ProxyFactory: 这个类,有很多属性,比如interface,advice,targetSource等等,被赋值之后,调用了DefaultAopProxyFactory的createAopProxy方法创建代理。
下面是最后的这个方法:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
包装后的代理对象为JdkDynamicAopProxy,还有CglibAopProxy(如果对象不是接口)。
当方法调用时候,会进入JdkDynamicAopProxy对象的invoke方法
实例化了一个ReflectiveMethodInvocation, 最后一层一层调用到 反射类Method的invoke方法,进入了本地代码区域。