书籍: 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方法,进入了本地代码区域。