一、本次学习的软件版本介绍

JDK 1.8+Maven 3.5+IDEA2018+SpringFramework 5.1.4

二、环境搭建

  • Spring的jar包
咱们能够通过maven的核心仓库来获取对应版本的依赖(上网找-搜spring-看到springcontext)<dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-context</artifactId>    <version>5.1.4.RELEASE</version></dependency>
  • Spring的配置文件
1. 配置文件的搁置地位: 任意地位 没有硬性要求2. 配置文件的命名:没有硬性要求,不过官网倡议:applicationContext.xml思考:你不通知spring你的配置文件在哪,它怎么去拉配置呢?所以咱们前面要配置对应【配置文件】的门路备注:咱们能够通过下图所示创立对应的配置文件


三、Spring的外围API

  • ApplicationContext
作用:Spring提供的的这个ApplicationContext这个工厂,最重要的是为了对象的创立益处: 解耦合
  • ApplicationContext接口类型
>为什么是接口?因为接口的目标是为了屏蔽实现的差别(谁实现我,谁就必须实现我所申明的办法)>那么Spring的接口实现类有哪些呢?非WEB环境:ClassPathXmlApplicationContext (比方main junit等办法)WEB环境: XmlWebApplicationContext>如何证实下面说的是正确的呢?首先为了保障有WEB环境的实现类,咱们先导入上面这个依赖<dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-webmvc</artifactId>   <version>5.1.4.RELEASE</version></dependency>第二步:咱们应用 CTRL+H 去查看该类的继承关系,那么咱们就找到了如下图

  • Application的实现类都是重量级资源
》毕竟属于创建对象的重要办法,所以其肯定占用了大量的内存》不会频繁地创建对象:一个利用只会创立一个工厂对象》在多线程并发拜访的时候肯定是线程平安的
  • 开发你的第一个Spring程序吧!
    其实和第一节的通过工厂形式获取对象的形式一样,咱们通过在配置文件获得惟一的类的全限定名来获取对象,上面为开发步骤
1》创立类:须要什么类,就配置什么类2》配置applicationContext.xml文件    <bean id="user" class="cn.paul.spring.demo.hellospring.entity.User"/>这里的id肯定是惟一的,class是类的权限定名,这就像咱们结尾所学习的配置文件的k-v对一样3》通过工厂,取得对象   ApplicationContext          |- ClassPathXmlApplicationContext (Junit或main等非web的环境下应用)          |- XmlWebApplicationContext(在web环境下应用)4》demo展现public class TestSpring {    @Test    void test01(){        //获取Spring工厂(传入对应的文件门路)        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");        //通过Spring工厂创建对象        User user = ctx.getBean("user", User.class);        System.out.println("user:"+user);    }}备注:对于非WEB的环境,你须要告知Spring你的配置文件在哪里!!
  • 第一个程序后,你应该要对上面这些细节有理解哦
第一点,通过下面的getBean办法传入的是配置文件的id和对应的类名称,那么很显著通过这种形式,能很好地去让Spring确定你须要创立哪个Bean(在Spring中也叫component)第二点,咱们还有一种getBean(User.class),通过这种形式来创建对象,比拟好的一点就是开发者能够略微懒一下,然而这是有限度的,如果你在配置文件中有申明到两个bean,而这两个bean所对应的Class名称都一样,都为这个同一个类的全限定名,那么在运行的时候就会报NoUniqueBeanDefinitionException 这个异样//通过这种形式取得对象,就不须要强制类型转换Person person = ctx.getBean("Person",Person.class);//以后Spring的配置文件中,只能有一个<bean class是Person类型Person person = ctx.getBean(Person.class);//获取的是Spring工厂配置文件中所有的bean标签的id值(看英文的复数便知)String[] beanDefinitionNames = ctx.getBeanDefinitionNames();//依据class的类型取得Spring配置文件中对应的id值String[] beanNamesForType = ctx.getBeanNamesFortype(Person.class);//上面两个办法都能用于判断是否存在指定id 的beanctx.containsBeanDefinition("指定的id");ctx.containsBean("指定的id")
  • 配置文件中须要留神的细节
a)咱们先来思考一个问题,如果咱们只是配置了一个只含有class标签的bean,Spring会帮咱们创立吗?如下<bean class="cn.paul.spring.demo.hellospring.entity.User"/>答案是:能够的,然而必须保障如果你想理论地应用上该对象,那么这个bean要保障惟一第二问题:既然上面对bean的定义是能够,那么Spring是否有给它定义“id值”呢?咱们能够通过 ctx.getBeanDefinitionNames()来获取对应的id值以做出判断咱们会发现其实Spring其实会给这个只申明了class名称的bean对应的id值的,其命名规定为:类的全限定名+ # + 下标如:cn.paul.spring.demo.hellospring.entity.User#0咱们注意一下最初一个下标,为什么下标是数组0呢?莫非还有1,2,3.....?其实我揣测可能是这样的,咱们能够在配置文件配置多个只带class名称的beanSpring也会给他们对应的默认id值(前面下标扭转即可)b) 只定义class名称的bean的利用场景   1> 如果这个bean只须要应用一次,那么就能够省略id值   2> 如果这个bean会应用屡次,或者被其余bean援用则须要设置id值c) name的属性除了在bean标签内定义id和class属性外,还能够定义name属性作用:用于在Spring的配置文件中,为bean对象设置别名(小名)依照咱们的生存教训,咱们晓得本名只能有一个(就像这里的id属性),然而咱们能够有很多个别名小名(就像这里的name属性,然而留神是指只针对一个bean对象)问题:它和id属性有什么区别呢?先说相同点:    1.ctx.getBean("id|name") --> Object (通过id或name,都能够创建对象)然而留神:能够定义多个name,之间用逗号宰割即可,然而不能在不同的bean应用同一个别名    2. <bean id="" class="" />    等效       <bean name="" class="" />    3. 为什么要有name这个属性呢?    这是因为在晚期Spring与Struts1整合的时候,对于bean的命名必须是以/结尾的    然而晚期的xml是不容许id以/结尾的,所以导致说可用name来匹配这种非凡的命名    最初随着技术的倒退,当初xml也容许id以/结尾了,所以说name这个属性多多少少    带有一点历史的痕迹    4. 对于ctx工厂提供的办法    ctx.containsBeanDefinition("字符串名称")只能判断是否存在指定id的bean    不能判断name值 但    ctx.containsBean("字符串名称")既能够判断是否存在指定id值的bean,也能够    判断name值(所以当前尽量用这个吧,比拟好记)
  • Spring工厂对上述的底层实现原理(简易版)
1.Spring框架通过ClassPathXmlApplicationContext工厂读取配置文件 applicationContext.xml 2.获取到配置文件标签的相干信息,比方id的值=account,class的值=cn.paul.entity.User 3.通过反射去创建对象Class<?> clazz =  Class.forName("class的值");User user = clazz.newInstance();4.留神一个问题,通过反射能够创立以任何修饰符润饰的构造方法的类的对象(回顾爆破)同时要晓得反射的底层其实是调用了该类的构造方法,并且首先调用的是无参结构     Class<?> clazz = Class.forName("class的值");    User user = clazz.newInstance();等效于    User user = new User();
  • 思考:在spring的开发中,是不是所有的对象,都会交由Spring工厂来创立呢
实践上来说,因为应用Spring工厂能解耦合的起因,的确是能够通过工厂来创立的然而有特例,比方操作数据库的长久层DAO,或者叫entity是不会交给Spring创立的而是交给长久层框架比方mybatis进行创立,毕竟entity生来是操作数据库的,和数据库做映射关系