Spring简介
- Spring是轻量级的开发框架,根本使命在于简开发,Spring 采用了4个关键策略
- 基于POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口松耦合
- 基于切面和惯性进行声明式编程
- 通过切面和模板减少样板式代码
- Spring 是面向 Bean 的编程(Bean Oriented Programming, BOP) , Bean 在 Spring 中才是真正的主角
-
注解使用
-
配置组件
- @Configuration:把一个类作为IoC容器,它的某个方法上如果使用了@Bean注解,则会将方法返回值作为容器中的一个Bean
- @ComponentScan:在配置类上加上该注解,会扫描该配置类所在的包下的所有配置类,并加入IoC容器
- @Scope:用于指定作用域
- @Lazy:延迟初始化
- @Conditional:Spring4开始提供,作用是按照一定的条件判断,满足条件给容器注册Bean
- @Import:导入外部资源
- @PostConstruct:用于指定初始化方法
- @PreDestory:用于指定销毁方法
- @DependsOn:定义Bean初始化和销毁时的顺序
-
自动装配组件
- @Componet、@Service、@Controller、@Repository泛指组件
- @Value:普通数据类型赋值
- @Autowired、@Resource、@Qualifier:依赖注入组件
- @PropertySource:读取配置文件
- @Primary:自动装配多个Bean候选者时,该注解的Bean作为首选在
-
织入组件
- ApplicationContextAware:可以通过这个上下文环境对象得到Spring容器中的Bean
- BeanDefinitionRegistryPostProcessor:实现了BeanFascoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition
-
切面组件
- @EnableTransactionManagement:添加对事务管理的支持
- @Transactional:配置声明式事务信息
-
模块划分
-
Spring框架源码模块划分
-
核心模块
-
切面编程
-
数据访问与集成
-
Web组件
-
通信报文
-
集成测试
-
集成兼容
-
各模块之间依赖关系
-
核心原理
-
Spring 中最核心的功能要数IoC Container和AOP,源码分析也是从此开始
-
关键类及类图
- BeanFactory
- 典型的工厂模式,是IoC容器的最顶层设计
- 定义了IoC容器的基本功能规范,有众多的子类为不同的使用场景提供了不同实现
- ApplicationContext
- 继承了BeanFactory。属于Spring 提供的高级容器
- 在基础容器之上还提供了许多容器之外的功能,都是通过继承不同的接口实现的
- AbstractApplicationContext是一个ApplicationContext的关键抽象实现,有众多子类实现
- BeanDefinition
- IoC容器管理的许多Bean以及Bean之间的关系,在Spring中是以BeanDefinition形式表述
- IoC容器管理的许多Bean以及Bean之间的关系,在Spring中是以BeanDefinition形式表述
- BeanWapper
- BeanDefinitionReader
- 主要完成对于Bean的解析,Spring 配置文件
- 主要完成对于Bean的解析,Spring 配置文件
- BeanFactory
源码分析
启动入口
-
Spring框架的启动入口是上下文对象AbstractApplicationContext类的
refresh()
方法refresh()
是一个模板方法,定义了IoC容器的启动流程。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 prepareRefresh(); //2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动 // 创建容器的关键方法 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //3、为BeanFactory配置容器特性,例如类加载器、事件处理器等 prepareBeanFactory(beanFactory); try { //4、为容器的某些子类指定特殊的BeanPost事件处理器 postProcessBeanFactory(beanFactory); //5、调用所有注册的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory); //6、为BeanFactory注册BeanPost事件处理器. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 registerBeanPostProcessors(beanFactory); //7、初始化信息源,和国际化相关. initMessageSource(); //8、初始化容器事件传播器. initApplicationEventMulticaster(); //9、调用子类的某些特殊Bean初始化方法 onRefresh(); //10、为事件传播器注册事件监听器. registerListeners(); //11、初始化所有剩余的单例Bean finishBeanFactoryInitialization(beanFactory); //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { // s logger.warn(); } //13、销毁已创建的Bean destroyBeans(); //14、取消refresh操作,重置容器的同步标识。 cancelRefresh(ex); throw ex; } finally { //15、重设公共缓存 resetCommonCaches(); } } }
-
通过xml配置的形式使用Spring时,Spring是以ClassPathXmlApplicationContext为起点进行启动的。可以从创建对象的源码中发现,在创建对象的时候调用了继承自父类的
refresh()
方法// 启动Spring,以及使用 public static void main(String[] args) { // 1. 创建ClassPathXmlApplicationContext对象 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.properties"); // 获取上下文中的对象 User user = (User) context.getBean("user"); System.out.println(user.getUsername()); } //--------------------------------------分析-------------------------------------- // 常用构造方法 public ClassPathXmlApplicationContext(String configLocation) throws BeansException { // 2. 调用重载的构造方法 this(new String[] {configLocation}, true, null); } // 重载构造方法 public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); // xml配置文件的解析 setConfigLocations(configLocations); // 3. 关键代码:调用了refresh()方法 if (refresh) { refresh(); } }
-
通过注解的形式使用Spring时,Spring是以AnnotationConfigApplicationContext 为起点进行启动的。可以从创建对象的源码中发现,在创建对象的时候调用了继承自父类的
refresh()
方法// 启动Spring方式1,手动注册、手动启动 public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(BeanConfig.class); context.refresh(); User user = context.getBean(User.class); user.say(); } // 启动Spring方式2,直接通过配置文件创建 public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); User user = context.getBean(User.class); user.say(); } // 启动Spring方式3,通过包路径扫描 public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("cn.com.rxdu.jobgrab"); User user = context.getBean(User.class); user.say(); } //-------------------------------------分析---------------------------------- // 通过配置文件创建构造方法 public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); // 配置文件解析注册 register(componentClasses); // 关键代码:调用了refresh()方法 refresh(); } // 通过包路径扫描创建构造方法 public AnnotationConfigApplicationContext(String... basePackages) { this(); // 包扫描 scan(basePackages); // 关键代码:调用了refresh()方法 refresh(); }
-
结合SpringMVC使用时,Spring是以ContextLoaderListener为起点进行启动的。
- 在web.xml中配置监听器,然后将项目部署到web容器,比如Tomcat中时。
- web容器启动时会启动监听,调用初始化方法
contextInitialized()
。 - 在此过程中,会默认创建上下文对象XmlWebApplicationContext,并且会调用该对象的
refresh()
方法
<!-- 系统组件加载顺序:context-param -> listener -> filter -> servlet --> <!-- spring 配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/applicationContext.xml</param-value> </context-param> <!-- 监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置dispatcherServlet --> <servlet> <servlet-name>ota</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/mvc-core-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
// ContextLoaderListener类的初始化方法 public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } // 初始化web容器 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { // 检测servlet容器中是否存在spring上下文对象,如果存在直接抛出异常 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { // 日志作了删减处理 throw new IllegalStateException(); } // 此处省略部分非关键代码........ try { // 关键代码: 创建spring上下文对象 if (this.context == null) { // 会查询web.xml配置中是否存在contextClass属性配置 // 如果存在,根据该属性的值创建对相应的Spring上下文对象 // 如果不存在,则根据spi机制,查找ContextLoader.properties文件 // 根据ContextLoader.properties文件属性值默认创建 XmlWebApplicationContext // 详细逻辑查看源代码 this.context = createWebApplicationContext(servletContext); } // XmlWebApplicationContext间接实现了ConfigurableWebApplicationContext if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { if (cwac.getParent() == null) { ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } // 关键代码 读取相应的配置并且刷新context对象 configureAndRefreshWebApplicationContext(cwac, servletContext); } } // 将spring上下文对象加入到Servlet容器 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); // 此处省略部分非关键代码........ return this.context; } catch (RuntimeException | Error ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } } // 通过refresh启动Spring protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { // 此处省略部分代码........ wac.refresh(); }
-
使用SpringBoot时,Spring是以SpringApplication为起点进行启动的。在执行
run()
方法时,会创建上下文对象,最终创建的是AnnotationConfigServletWebServerApplicationContext,然后执行refresh()
方法// 启动SpringBoot public static void main(String[] args) { SpringApplication.run(DemoApplication.class,args); } // 调用了SpringApplication 类的 ConfigurableApplicationContext 方法 public ConfigurableApplicationContext run(String... args) { // 省略部分代码....... ConfigurableApplicationContext context = null; try { // 环境配置解析相关 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); configureIgnoreBeanInfo(environment); // 创建banner图 Banner printedBanner = printBanner(environment); // 创建上下文对象,最终创建的是 AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(); context.setApplicationStartup(this.applicationStartup); // 初始化上下文对象 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 刷新Spring容器 refreshContext(context); // 省略部分代码....... } // 省略部分代码....... return context; } // 刷新上下文 private void refreshContext(ConfigurableApplicationContext context) { if (this.registerShutdownHook) { shutdownHook.registerApplicationContext(context); } refresh(context); } protected void refresh(ConfigurableApplicationContext applicationContext) { //关键代码 refresh applicationContext.refresh(); }
容器初始化
- 步骤总结
- 调用
refresh()
方法之后,执行obtainFreshBeanFactory()
方法,创建容器 - 生成容器对象DefaultListableBeanFactory
- 加载BeanDefinition放入到容器中
- 根据DefaultListableBeanFactory创建XmlBeanDefinitionReader或者AnnotatedBeanDefinitionReader来解析bean定义信息
- 将解析好的bean信息定义封装成BeanDefinition对象,再将BeanDefinition对象封装为BeanDefinitionHolder对象
- BeanDefinitionHolder对象中持有BeanDefinition以及别名信息
- 调用容器对象DefaultListableBeanFactory的
registerBeanDefinition()
方法将BeanDefinition信息放到容器中的属性Map<String, BeanDefinition> beanDefinitionMap
中
- 将生成的容器对象DefaultListableBeanFactory加入到上下文对象的属性beanFactory中
- 至此,完成了容器的创建,并将对象的定义信息交给了对象工厂类,相当于IoC容器初始化步骤完成。
- 调用
-
根据Spring 启动的入口
refresh()
方法来进行分析public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 prepareRefresh(); //2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 // 子类的refreshBeanFactory()方法启动 // 创建容器的关键方法 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 省略部分代码............ } }
-
容器的创建关键方法是
obtainFreshBeanFactory()
,最终返回的BeanFactory是DefaultListableBeanFactory,并存储到了AbstractRefreshableApplicationContext的属性中protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory(); } protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 创建 DefaultListableBeanFactory 对象 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); // 加载BeanDefinition loadBeanDefinitions(beanFactory); // 加入到上下文属性中 this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
-
在创建容器的过程中,有一个步骤是加载BeanDefiniton,这个步骤是将bean定义封装为BeanDefinition,加载到容器当中。
- 其中有两个关键对象
- BeanDefinition的作用是用于在Spring容器初始化的时,将bean的参数转化为Spring内部的BeanDefinition的结构
- BeanDefinitionHolder顾名思义就是对BeanDefinition的持有,同时持有的包括BeanDefinition的名称和别名
- 如果bean的定义使用注解,则使用AnnotatedBeanDefinitionReader加载解析
- 如果bean的定义在xml文件中配置,则使用XmlBeanDefinitionReader加载解析
- 在DefinitionReader加载解析完成之后,生成了BeanDefinitionHolder对象
- 然后调用DefaultListableBeanFactory的
registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
方法将BeanDefinition存储到容器中
// DefaultListableBeanFactory中的属性,beanDefinition容器 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // 省略部分代码...... // 从beanDefinitionMap中获取名称对应的BeanDefinition BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { // 如果已经存在并且不允许覆盖直接抛出异常 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } // 省略部分代码...... this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 省略部分代码...... this.beanDefinitionMap.put(beanName, beanDefinition); } // 省略部分代码...... }
- 其中有两个关键对象
依赖注入
-
依赖注入即DI(Dependency Injection)主要做两件事:对象实例化和自动装配。
-
依赖注入的入口只有一个就是BeanFactory的
getBean()
方法- Spring默认是懒加载,所以在IoC容器的初始化阶段并没有生成bean对象,当调用BeanFactory的
getBean()
方法才实际创建对象。 - 如果设置了非懒加载,那么在容器启动的时候就需要生成bean对象,在容器启动的
refresh()
方法中有一个方法调用finishBeanFactoryInitialization(beanFactory);
,此方法就是非懒加载情况下的对象实例化方法,该方法最终也是调用BeanFactory的getBean()
方法去创建对象的 - 因此,依赖注入就是从
getBean()
开始的
- Spring默认是懒加载,所以在IoC容器的初始化阶段并没有生成bean对象,当调用BeanFactory的
-
步骤总结
-
调用
getBean()
方法 -
查找需要的bean是否在缓存中
-
如果存在于缓存中,直接获取并返回
-
如果不存在则创建对象,通过层层调用之后,通过反射创建对象实例,并将创建的对象封装为BeanWapper对象
-
通过AbstractAutowireCapableBeanFactory类的
populateBean()
方法完成创建对象的属性注入 -
属性注入之后,执行
initializeBean(beanName, exposedObject, mbd);
方法。完成bean的初始化,代理等操作 -
将生成的对象放入到缓存中
- 循环依赖依靠缓存来解决,递归调用
getBean()
方法 - 一级缓存:成熟的已经注入完属性的bean
- 二级缓存:纯净的bean,还没有依赖注入
- 三级缓存:创建代理Bean的Factory
- 递归调用缓存使用示意
- 循环依赖依靠缓存来解决,递归调用
-
实例化对象
-
从依赖注入的入口开始分析,即从调用AbstractBeanFactry的
getBean()
开始// AbstractBeanFactry类的getBean()方法 public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); // 实例对象 Object beanInstance; // Eagerly check singleton cache for manually registered singletons. // 检查实例是否在缓存中存在(会依次检查多级缓存,缓存中是共享的状态) Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 省略部分代码...... // 如果要获取的bean对象名字是&开头的那么直接返回 sharedInstance // 如果名字不以&开头,并且不是工厂类那么直接返回 sharedInstance // 如果名字不以&开头,并且是工厂类那么经过一系列处理之后直接返回 sharedInstance beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 省略部分代码...... Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); // 省略部分代码...... } return adaptBeanInstance(name, beanInstance, requiredType); }
-
首先检查缓存中是否已经存在bean对象,如果存在直接返回,如果不存在则通过
createBean()
创建新对象protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 省略部分代码...... //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } // 省略部分代码...... Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; // 省略部分代码...... }
-
在
createBean()
方法中调用了AbstractAutowireCapableBeanFactory类的doCreateBean()
方法创建bean对象protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 创建BeanWrapper对象 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 真实创建对象实例的方法 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 省略部分代码....... // 依赖注入方法 populateBean(beanName, mbd, instanceWrapper); // bean初始化:设置代理等初始化方法调用等 exposedObject = initializeBean(beanName, exposedObject, mbd); // 省略部分代码....... return exposedObject; }
-
在
doCreateBean()
方法中调用了createBeanInstance()
方法,根据定义的构造方法创建对象protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 省略部分代码...... // 有参构造 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 省略部分代码...... // 无参构造 return instantiateBean(beanName, mbd); } protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; // 省略部分代码...... // 通过反射创建对象 if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); } // 将实例化的对象封装成BeanWrapper BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
属性注入
-
属性的注入是在创建实例对象的时候调用 的,在创建对象的方法
doCreateBean()
中,有一部分是populateBean()
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 省略部分代码....... // 依赖注入方法 populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); // 省略部分代码....... return exposedObject; } //将Bean属性设置到生成的实例对象上 protected void populateBean(String beanName , RootBeanDefinition mbd , @Nullable BeanWrapper bw) { // 省略部分代码...... //获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 省略部分代码...... //对属性进行注入 applyPropertyValues(beanName, mbd, bw, pvs); }
切面编程
- 步骤总结
- 在spring启动阶段,会向容器中注册许多BeanPostProcesser
- 在bean实例化阶段,会调用已经注册好的BeanPostProcesser实例的
postProcessAfterInitialization()
方法 - 最终通过AbstractAutoProxyCreator类的
postProcessAfterInitialization()
方法,完成代理对象的创建
-
在容器启动阶段会在上下文对象的beanFactory中注册多个bean后置处理器,其中会有一个AnnotationAwareAspectJAutoProxyCreator
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //为BeanFactory配置容器特性,例如类加载器、事件处理器等 prepareBeanFactory(beanFactory); try { //4、为容器的某些子类指定特殊的BeanPost事件处理器 postProcessBeanFactory(beanFactory); //5、调用所有注册的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory); //6、为BeanFactory注册BeanPost事件处理器. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 registerBeanPostProcessors(beanFactory); // 省略部分代码...... }
-
在依赖注入的bean实例化阶段,会调用bean的初始化方法,在此阶段会执行容器初始化时注册的bean处理器方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 省略部分代码....... // 依赖注入方法 populateBean(beanName, mbd, instanceWrapper); // 初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); // 省略部分代码....... return exposedObject; } // bean初始化方法 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { // 省略部分代码.... Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 在初始化之前调用bean后置处理器方法, @PostConstruct的方法在这一步执行 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } // 省略部分代码.... // 初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); // 省略部分代码.... if (mbd == null || !mbd.isSynthetic()) { // 在初始化之后调用bean后置处理器方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
-
在执行bean后置处理器方法
applyBeanPostProcessorsAfterInitialization()
,会执行容器初始化阶段设置的所有BeanPostProsser子类的postProcessAfterInitialization()
方法。AOP相关的AnnotationAwareAspectJAutoProxyCreator,会调用父类AbstractAutoProxyCreator的相关方法// AbstractAutoProxyCreator public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 对初始化的bean进行一层包装 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 创建AOP代理对象 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
MVC
-
九大组件
-
关系类图
-
步骤总结
-
在Spring启动时,会初始化一些非懒加载的Bean。其中有与MVC相关的重要的两个类RequestMappingHandlerMapping与RequestMappingHandlerAdapter
- RequestMappingHandlerMapping对象在实例化时,会将所有的Controller中对应的支持请求的方法以及支持访问的地址封装成HandlerMethod,存储到属性当中
-
在接收到请求时,会创建DispatcherServlet实例对象。
- 实例创建时会根据继承关系,调用HttpServletBean中的
init()
方法,最终执行到initStrategies()
来完成SpringMVC的组件初始化 - 组件初始化过程中会将RequestMappingHandlerMapping与RequestMappingHandlerAdapter加入到属性DispatcherServlet属性中,分别是
handlerMappings
、handlerAdapters
- 实例创建时会根据继承关系,调用HttpServletBean中的
-
接受到请求时,会先根据DispatcherServlet属性中的
handlerMappings
查找具体的执行HandlerMethod,然后将该HandlerMethod与拦截器封装为HandlerExecutionChain对象 -
找到HandlerAdapter反射执行HandlerMethod对象中的具体Controller方法
-
-
web容器启动时,会启动Spring容器,Spring启动时会在
refresh()
方法中执行finishBeanFactoryInitialization()
初始化所有非懒加载单例对象public void refresh() throws BeansException, IllegalStateException { // 省略部分代码...... ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // 省略部分代码...... // 初始化所有非懒加载单例 finishBeanFactoryInitialization(beanFactory); // 省略部分代码...... }
-
其中有一个类RequestMappingHandlerMapping,这个类是HandlerMapping的关键类,该类间接实现了InitializingBean接口,因此在实例化之后会执行其
afterPropertiesSet()
方法。通过继承关系最终执行父类AbstractHandlerMethodMapping的afterPropertiesSet()
方法public void afterPropertiesSet() { initHandlerMethods(); } protected void initHandlerMethods() { for (String beanName : getCandidateBeanNames()) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { // 关键方法 processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); } protected void processCandidateBean(String beanName) { // 省略部分代码...... if (beanType != null && isHandler(beanType)) { // 关键方法 detectHandlerMethods(beanName); } }
-
通过
detectHandlerMethods()
方法,将所有的映射到的方法以及所属的handler封装为MappingRegistry,加入到RequestMappingHandlerMapping的属性中protected void detectHandlerMethods(Object handler) { // 省略部分代码...... // 所有请求映射到的controller的方法 methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); // 根据方法名称、请求映射、所属controller进行注册 registerHandlerMethod(handler, invocableMethod, mapping); }); } protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method); } // RequestMappingHandlerMapping类的属性 private final MappingRegistry mappingRegistry = new MappingRegistry();
-
MappingRegistry时一个内部类,结构如图
class MappingRegistry { // 存储的是url与controller方法的对应关系 private final Map<T, MappingRegistration<T>> registry = new HashMap<>(); // 映射的url地址 private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap<>(); // 方法名称 private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>(); // 省略部分代码...... }
-
web容器启动时,会启动Spring容器。在接收到请求时会根据web.xml配置,调用DispatchServlet的
init()
方法进行初始化// 根据DispatchServlet的继承体系找到HttpServletBean 继承了HttpServlet public final void init() throws ServletException { // 省略部分代码.... initServletBean(); }
-
初始化容器方法
init()
执行之后,调用到了FrameworkServlet的initServletBean()
方法protected final void initServletBean() throws ServletException { // 省略部分代码...... // 关键代码,初始化web上下文 this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); // 省略部分代码...... }
-
在初始化上下文的方法中,执行到了关键代码
onRefresh()
protected WebApplicationContext initWebApplicationContext() { // 省略部分代码...... onRefresh(wac); // 省略部分代码...... }
-
通过
onRefresh()
方法,调用初始化策略,初始化SpringMVC的九大组件protected void onRefresh(ApplicationContext context) { initStrategies(context); } protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); // 初始化处理器映射器 initHandlerMappings(context); // 初始化处理器适配器 initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
-
在初始化处理器映射器时,将RequestMappingHandlerMapping加入到DispatchServlet属性
handlerMappings
中private List<HandlerMapping> handlerMappings; private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // 关键代码,将IoC容器中的HandlerMapping 找出来,加入到 handlerMappings中 Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // 排序 AnnotationAwareOrderComparator.sort(this.handlerMappings); } } // 省略部分代码...... }
-
在接受到web请求时,会调用servlet的
doService()
方法,最终执行 到了DispatcherServlet的doDispatch()
方法。protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // 省略部分代码...... doDispatch(request, response); // 省略部分代码...... }
-
在
doDispatch()
方法中首先会根据请求地址,去handlerMappings
中 查找对应的具体执行方法,根据查询结果返回一个HandlerMethod
对象。然后将对象以及所有的Interceptor
封装为执行链对象HandlerExecutionChain
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerExecutionChain mappedHandler = null; // 省略部分代码...... // 查找具体对应的handler mappedHandler = getHandler(processedRequest); // 省略部分代码...... } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 省略部分代码...... HandlerExecutionChain handler = mapping.getHandler(request); // 省略部分代码...... } public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 根据请求url找到RequestMappingHandlerMapping属性MappingRegistry中的执行方法 Object handler = getHandlerInternal(request); // 省略部分代码...... // 封装执行链 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 省略部分代码...... return executionChain; } // 将具体的执行器,和拦截器封装为HandlerExecutionChain对象 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { // 省略部分代码...... for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(request)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } // HandlerExecutionChain结构 public class HandlerExecutionChain { // 省略部分代码...... // 具体的处理器对象controller private final Object handler; private final List<HandlerInterceptor> interceptorList = new ArrayList<>(); // 省略部分代码...... }
-
找到与HandlerMapping对应的HandlerAdapter。此处应该是RequestMappingHandlerMapping与之对应的RequestMappingHandlerAdapter。这两个类都是在Spring启动时加入到Spring容器中的。然后反射调用实际的Handler方法,返回ModelAndView对象
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // 省略部分代码...... HandlerExecutionChain mappedHandler = null; // 省略部分代码...... mappedHandler = getHandler(processedRequest); // 省略部分代码...... // 找到对应的HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 省略部分代码...... // 执行具体处理逻辑 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // 省略部分代码...... } // 父类为AbstractHandlerMethodAdapter类的handler方法 public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; // 省略部分代码...... mav = invokeHandlerMethod(request, response, handlerMethod); // 省略部分代码...... return mav; } protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // 省略部分代码...... ServletWebRequest webRequest = new ServletWebRequest(request, response); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); // 省略部分代码...... // 关键调用 invocableMethod.invokeAndHandle(webRequest, mavContainer); // 省略部分代码...... return getModelAndView(mavContainer, modelFactory, webRequest); // 省略部分代码...... } public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 关键调用 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); // 省略部分代码...... } public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 参数处理,方法执行所需参数已经封装到了 HandlerMethod对象中,有了需要的参数和请求参数就可以做处理了 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); // 省略部分代码...... return doInvoke(args); } protected Object doInvoke(Object... args) throws Exception { Method method = getBridgedMethod(); // 省略部分代码...... return method.invoke(getBean(), args); // 省略部分代码...... }
-
doDispatch()
中的后续流程不再分析