如何将网站开发成微信小程序,如何做网站更新,微信营销软件功能,logo设计网站排行榜IOC容器概述
ApplicationContext接口相当于负责bean的初始化、配置和组装的IoC容器. Spring为ApplicationContext提供了一些开箱即用的实现, 独立的应用可以使用 ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext#xff0c;web应用在web.xml配置监 听web应用在web.xml配置监 听提供xml位置和org.springframework.web.context.ContextLoaderListener即可初始化 WebApplicationContextIoC容器.
配置元数据
配置元数据配置了应用中实例的实例化、配置以及组装的规则SpringIoC容器通过此配置进行管理 Bean. 配置元数据有以下几种方式 基于XML配置 清晰明了简单易用 基于Java代码配置无xml,通过 Configuration 来声明配置、对象实例化与依赖关系 基于Java注解配置少量的XML( context:annotation-config/ )通过注解声明实例化类与依赖关系 后续的分析基于XML配置, 与Java代码和注解大体上的机制是一样
实例化容器
实例化容器非常简单只需要提供本地配置路径或者根据 ApplicationContext 的构造器提供相应的资 源(Spring的另一个重要抽象)即可.
ApplicationContext context new
ClassPathXmlApplicationContext(application.xml);

refresh()方法的实现代码如下
public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {this.prepareRefresh(); // 准备工作ConfigurableListableBeanFactory beanFactory this.obtainFreshBeanFactory(); // 获取ConfigurableListableBeanFactory最终的目的是DefaultListableBeanFactorythis.prepareBeanFactory(beanFactory); // 准备bean工厂try {this.postProcessBeanFactory(beanFactory); // 一个空的实现注意这里的spring版本号为5.3xthis.invokeBeanFactoryPostProcessors(beanFactory); // 注册bean的工厂this.registerBeanPostProcessors(beanFactory);this.initMessageSource(); // Spring 从所有的 Bean 定义中抽取出来了BeanPostProcessor然后都注册进 beanPostProcessors等待后面的的顺序调用 注册BeanPostProcessorthis.initApplicationEventMulticaster(); // 初始化事件监听多路广播器this.onRefresh(); // 一个空的实现this.registerListeners(); // 注册监听器this.finishBeanFactoryInitialization(beanFactory); // 到了spring加载流程最复杂的一步开始实例化所有的bdthis.finishRefresh();// 刷新完成工作} catch (BeansException var9) {if (this.logger.isWarnEnabled()) {this.logger.warn(Exception encountered during contextinitialization - cancelling refresh attempt: var9);}this.destroyBeans();this.cancelRefresh(var9);throw var9;} finally {this.resetCommonCaches();}}}loadBeanDefinitions:
ConfigurableListableBeanFactory beanFactory this.obtainFreshBeanFactory();this.refreshBeanFactory();this.loadBeanDefinitions(beanFactory);protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)throws BeansException, IOException {XmlBeanDefinitionReader beanDefinitionReader newXmlBeanDefinitionReader(beanFactory);beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));this.initBeanDefinitionReader(beanDefinitionReader);this.loadBeanDefinitions(beanDefinitionReader);}1、传统的构建方式 我们沟通SpringMVCSpringFramework来构建一个web项目过程如下 创建一个maven-webapp项目 添加jar包依赖
dependencygroupIdorg.springframework/groupIdartifactIdspring-beans/artifactIdversion5.2.5.RELEASE/version
/dependency
dependencygroupIdcommons-logging/groupIdartifactIdcommons-logging/artifactIdversion1.2/version
/dependencyspring-context
spring-context-support
spring-core
spring-expression
spring-web
spring-webmvc
修改web.xml文件context-param!--配置上下文配置路径--param-namecontextConfigLocation/param-nameparam-valueclasspath:applicationContext.xml/param-value
/context-param
!--配置监听器--
listenerlistenerclassorg.springframework.web.context.ContextLoaderListener/listener-class
/listener
listener
listener-classorg.springframework.web.util.IntrospectorCleanupListener/listener-class
/listener
!--配置Spring MVC的请求拦截--
servletservlet-namespringmvc/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-classinit-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:dispatcher-servlet.xml/param-value/init-param
/servlet
servlet-mappingservlet-namespringmvc/servlet-nameurl-pattern//url-patter
/servlet-mapping在resources目录下添加dispatcher-servlet.xml文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:mvchttp://www.springframework.org/schema/mvcxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd
!-- 扫描 controller --
context:component-scan base-packagecom.mashibingedu.controller /
!--开启注解驱动--
mvc:annotation-driven/
!-- 定义视图解析器 --
bean
classorg.springframework.web.servlet.view.InternalResourceViewResolverproperty nameprefix value//property namesuffix value.jsp/
/bean创建一个Controller
Controller
public class HelloController {RequestMapping(method RequestMethod.GET,path /index)public String index(Model model){model.addAttribute(key,Hello mashibing);return index;}
}
修改默认的index.jsp设置el表达式的解析
% page languagejava contentTypetext/html; charsetutf-8
pageEncodingutf-8 isELIgnoredfalse %
${key}运行项目
2、理解SpringBoot Spring Boot被官方定位为“BUILD ANYTHING”Spring Boot官方的概述是这么描述Spring Boot的。
Spring Boot makes it easy to create stand-alone, production-grade Spring based
Applications that you can just run.
// 通过Spring Boot可以轻松的创建独立的、生产级别的基于Spring 生态下的应用你只需要运行即可。
We take an opinionated view of the Spring platform and third-party libraries so
you can get started with minimum fuss. Most Spring Boot applications need
minimal Spring configuration.
//对于Spring平台和第三方库我们提供了一个固化的视图这个视图可以让我们在构建应用时减少很多麻
烦。大部分spring boot应用只需要最小的Spring 配置即可3、理解约定优于配置 约定优于配置是一种软件设计的范式主要是为了减少软件开发人员需做决定的数量获得简单的好 处而又不失灵活性。 简单来说就是你所使用的工具默认会提供一种约定如果这个约定和你的期待相符合就可以省略那些基础的配置否则你就需要通过相关配置来达到你所期待的方式。 约定优于配置有很多地方体现举个例子比如交通信号灯红灯停、绿灯行这个是一个交通规范。你可以在红灯的时候不停因为此时没有一个障碍物阻碍你。但是如果大家都按照这个约定来执行那么不管是交通的顺畅度还是安全性都比较好。 而相对于技术层面来说约定有很多地方体现比如一个公司会有专门的文档格式、代码提交规范、接口命名规范、数据库规范等等。这些规定的意义都是让整个项目的可读性和可维护性更强。
4、Spring Boot Web应用中约定优于配置的体现 那么在前面的案例中我们可以思考一下Spring Boot为什么能够把原本繁琐又麻烦的工作省略掉呢实际上这些工作并不是真正意义上省略了只是Spring Boot帮我们默认实现了。 而这个时候我们反过来思考一下Spring Boot Web应用中相对Spring MVC框架的构建而言它的约定优于配置体现在哪些方面呢 Spring Boot的项目结构约定Spring Boot默认采用Maven的目录结构其中 src.main.java 存放源代码文件 src.main.resource 存放资源文件 src.test.java 测试代码 src.test.resource 测试资源文件 target 编译后的class文件和jar文件 内置了嵌入式的Web容器在Spring 2.2.6版本的官方文档中3.9章节中有说明Spring Boot支持 四种嵌入式的Web容器 Tomcat Jetty Undertow Reactor Spring Boot默认提供了两种配置文件一种是application.properties、另一种是 application.yml。Spring Boot默认会从该配置文件中去解析配置进行加载。 Spring Boot通过starter依赖来减少第三方jar的依赖。 这些就是Spring Boot能够方便快捷的构建一个Web应用的秘密。当然Spring Boot的约定优于配置还不 仅体现在这些地方在后续的分析中还会看到Spring Boot中约定优于配置的体现。
5、Import注解 import注解是什么意思呢 联想到xml形式下有一个 形式的注解就明白它的作 用了。import就是把多个分来的容器配置合并在一个配置中。在JavaConfig中所表达的意义是一样的。 创建一个包并在里面添加一个单独的configuration
public class DefaultBean {
}
Configuration
public class SpringConfig {Beanpublic DefaultBean defaultBean(){return new DefaultBean();}
}
此时运行测试方法
public class MainDemo {public static void main(String[] args) {ApplicationContext acnewAnnotationConfigApplicationContext(SpringConfig.class);String[] defNamesac.getBeanDefinitionNames();for(String name:defNames){System.out.println(name);}}
}在另外一个包路径下在创建一个配置类。此时再次运行前面的测试方法打印OtherBean实例时 这个时候会报错提示没有该实例
public class OtherBean {
}
Configuration
public class OtherConfig {Beanpublic OtherBean otherBean(){return new OtherBean();}
}修改springConfig把另外一个配置导入过来
Import(OtherConfig.class)
Configuration
public class SpringConfig {Beanpublic DefaultBean defaultBean(){return new DefaultBean();}
}再次运行测试方法即可看到对象实例的输出。
6、深入分析EnableAutoConfiguration EnableAutoConfiguration的主要作用其实就是帮助springboot应用把所有符合条件的Configuration 配置都加载到当前SpringBoot创建并使用的IoC容器中。 再回到EnableAutoConfiguration这个注解中我们发现它的import是这样
Import(AutoConfigurationImportSelector.class)
public interface EnableAutoConfiguration {
但是从EnableAutoCOnfiguration上面的import注解来看这里面并不是引入另外一个Configuration。 而是一个ImportSelector。这个是什么东西呢
7、AutoConfigurationImportSelecto Enable注解不仅仅可以像前面演示的案例一样很简单的实现多个Configuration的整合还可以实现一些 复杂的场景比如可以根据上下文来激活不同类型的beanImport注解可以配置三种不同的class
第一种就是前面演示过的基于普通bean或者带有Configuration的bean进行诸如实现ImportSelector接口进行动态注入 实现ImportBeanDefinitionRegistrar接口进行动态注入 CacheService
public class CacheService {
}LoggerService
public class LoggerService {
}EnableDefineService
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Documented
Inherited --允许被继承
Import({MyDefineImportSelector.class})
public interface EnableDefineService {String[] packages() default ;
}MyDefineImportSelector
public class MyDefineImportSelector implements ImportSelector {
Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {//获得指定注解的详细信息。我们可以根据注解中配置的属性来返回不同的class//从而可以达到动态开启不同功能的目的annotationMetadata.getAllAnnotationAttributes(EnableDefineService.class.getName(),true).forEach((k,v) - {log.info(annotationMetadata.getClassName());log.info(k:{},v:{},k,String.valueOf(v));});return new String[]{CacheService.class.getName()};}
}
EnableDemoTest
SpringBootApplication
EnableDefineService(name mashibing,value mashibing)
public class EnableDemoTest {public static void main(String[] args) {ConfigurableApplicationContextcaSpringApplication.run(EnableDemoTest.class,args);System.out.println(ca.getBean(CacheService.class));System.out.println(ca.getBean(LoggerService.class));}
}了解了selector的基本原理之后后续再去分析AutoConfigurationImportSelector的原理就很简单了 它本质上也是对于bean的动态加载。