Hello,你们好,今天开始,小弟准备推出Spring系列的博客,但愿你们喜欢。关于Spring其实我就不用再多介绍了,作过Web开发的,基本都使用Spring,包括如今比较时尚的Spring cloud微服务架构,其实也是基于Spring boot ,Spring boot 说到底其实仍是传统的Spring三件套,只是避免了用户本身配置Bean,而是采用了自动配置,Spring boot后期有时间也专门给你们出一系列博客。这一期做为Spring的第一篇,先来点基础的,OK,来套路,文章结构:java
其实对于不少业务开发程序员来说,这个接口是比较陌生的,你们知道的是在初始化容器的时候直接指定文件路径,而后容器就初始化好了,这个Resource接口是Spring提供的,它为应用提供了更强的底层资源访问能力。比JDK自带的File和URL类不知道强了多少。列下类结构: 程序员
Resource res =new ServletContectResource(/WEB-INF/classes/spring/application.xml);
复制代码
看到代码,相信比较敏感的小伙伴应该感受到了,这种加载方式显然是不合适的,由于在使用不一样的资源类型时,必须使用相应的Resource资源类,这是比较麻烦的,是否能够在不现实使用Resource实现类的状况下,仅经过资源地址的特殊标识就能够访问相应的资源呢?Spring这么伟大的框架,固然是能够的。Spring不只可以经过"classpath:","file"等资源地址前缀识别不一样资源类型,还支持Ant风格带通配符的资源地址。Spring内部会经过资源加载器来根据不一样的资源路径选择相应的Resource实现类。避免的使用者本身选择实现类。web
先看下Spring内置的一些资源前缀表达的含义: spring
具体就不举例子了,Ant风格的通配符太经常使用了。sql
public class GaoshiApplication {
public static void main(String[] args) throws IOException {
PathMatchingResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
Resource[] res =resolver.getResources("file:/Users/zdy/Desktop/sql.txt");
for (Resource resource : res){
System.out.println(resource.getDescription()+"----"+resource.getFilename());
}
SpringApplication.run(GaoshiApplication.class, args);
}
}
复制代码
输出结果:
URL [file:/Users/zdy/Desktop/sql.txt]----sql.txt
复制代码
好了,其实这一小节为何要给你们讲Resource和PathMatchingResourcePatternResolver资源加载器呢,不少人可能感受没什么用,反正Spring内部本身使用就完了,跟我不要紧。其实不是的,老铁们,Spring内部本身使用不假,首先,知道点底层原理很差吗?其次,你们若是本身有配置文件在classpath下,而后想经过代码去加载(虽然这种需求很是少),那么你们就能够本身使用Spring提供的资源加载器了。这个加载器仍是很方便的,直接根据前缀加载资源,并且还支持Ant通配符。你说厉害不厉害。数组
BeanFactory,其实不少人听过,只是没有用过,你们启动容器的时候可能都是用的ApplicationContext的某个实现类,因此这个BeanFactory慢慢的都淡了,更别说它的实现类了。说下特性:bash
而后举个初始化BeanFactory的例子吧:session
//调用资源加载器加载Spring配置文件
PathMatchingResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
Resource res =resolver.getResource("classpath:/application.xml");
//建立默认Spring提供的BeanFactory实现类
DefaultListableBeanFactory bf =new DefaultListableBeanFactory();
//BeanDefinition 读取器,专门读取资源到容器
XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(bf);
//读取资源进到容器
reader.loadBeanDefinitions(res);
//此时容器初始化完毕后能够取里面的bean了.
bf.getBean("...");
复制代码
能够看到,代码比较繁琐,并且很啰嗦。BeanFactory的功能还比较弱,因此你们就当了解吧。架构
这个ApplicationContext其实就是老铁们常常说的Spring容器了。由于相对要重要一些,因此列了大体的类继承图: app
ApplicationContext ac =new ClassPathXmlApplicationContext("application.xml");
ApplicationContext ac =new FileSystemXmlApplicationContext(/User/Desktop/application.xml);
复制代码
ClassPathXmlApplicationContext若是没有前缀默认就是classpath: FileSystemXmlApplicationContext若是没有前缀默认就是 file:
而后再说一个,Spring容器不只能够经过xml文件来初始化,@Configuration注解你们应该知道,也是注册Bean用的,固然了,Spring也提供了相应的AnnotationConfigApplicationContext.
ApplicationContext context =new AnnotationConfigApplicationContext(Config.class);
复制代码
Config类就是咱们加了@Configuration的类了。
其实WebApplicationContext也属于ApplicationContext,为何单独拿出来说呢,由于比较重要。WebApplicationContext是Spring专门为Web应用准备的。它容许从相对于Web根目录的路径中装载配置文件完成初始化工做。WebApplicationContext与ServletContext能够相互得到.在非Web应用的环境下,Bean只有singleton和prototype两种做用域,而WebApplicationContext为Bean添加了三个新的做用域:request,session,global session。来看下类继承图:
而后说下WebApplicationContext和ServletContext是如何相互获取的,其实很简单,在WebApplicationContext里有ServletContext成员变量,直接get就完了。在ServletContext里有一个写死的attrbute,也是直接get..并且Spring提供了一个WebApplicationContextUtils来封装了这个写死的attribute.
其实就是直接调用了ServletContext.getAttribute(ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
复制代码
而后说下WebApplication的初始化,作过Web的都知道,其实要么在Web.xml里面配置一个ContextLoaderListener,要么配置一个自启动的LoaderServlet.其实比较简单了,我展现下ContextLoaderListener.
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
复制代码
若是不是根据xml文件启动Spring容器而是根据@Configuration类启动,其实也很简单.
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.zdy.Configuration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
复制代码
配置一个contextClass参数ApplicationContext改成AnnotationConfigWebApplicationContext,而后contextConfigLocation不是指定配置文件xml位置了,改成指定Configuration类的位置。就OK了。
最后,须要强调的是,因为Spring容器自带的Log4j功能,因此用户能够直接将Log4j的配置文件放置在类路径下,直接就生效了,可是,若是不在类路径下,须要在Web.xml中手动指定文件的位置和启动log4j的listener,这里我就不演示了,须要注意的是,这个log4j的listener或者servlet必须在spring容器的listenier或servlet前面。不要问为何。就是这么规定的。不过这点你们不经常使用,因此我只是提一提。
好了,其实你们也看出来了,讲Spring的时候我仍是偏向于使用的,Spring的底层深层次的原理其实设计到的很少。Spring这个至尊框架,我以为先要宏观使用上先整明白。后期有机会给你们多讲点底层实现。喜欢你们多关注接下来的Spring系列文章。Over,Have a good day .