Spring框架学习第一天

Spring概述

Spring是什么

Spring是分层的 Java SE/EE应用 full-stack(全栈) 轻量级开源框架

Spring的核心是 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)

Spring一个全栈应用框架, 提供了表现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多应用技术

Spring还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架

Spring发展历程

  • EJB
    1997 年,IBM提出了EJB 的思想
    1998 年,SUN制定开发标准规范 EJB1.0
    1999 年,EJB1.1 发布
    2001 年,EJB2.0 发布
    2003 年,EJB2.1 发布
    2006 年,EJB3.0 发布

  • Spring
    Rod Johnson( Spring 之父)
    改变Java世界的大师级人物

    2002年编著《Expert one on one J2EE design and development》
    指出了JavaEE和EJB组件框架中的存在的一些主要缺陷;提出普通java类依赖注入更为简单的解决方案。

    2004年编著《Expert one-on-one J2EE Development without EJB》
    阐述了JavaEE开发时不使用EJB的解决方式(Spring 雏形)
    同年4月spring1.0诞生

    2006年10月,发布 Spring2.0
    2009年12月,发布 Spring3.0
    2013年12月,发布 Spring4.0
    2017年9月, 发布最新 Spring5.0 通用版(GA)

Spring优势

  1. 方便解耦,简化开发
    通过Spring提供的 IOC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。 用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

  2. AOP编程的支持
    通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。

  3. 声明式事务的支持
    可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。

  4. 方便程序的测试
    可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。

  5. 方便集成各种优秀框架
    Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。

  6. 降低JavaEE API的使用难度
    Spring对JavaEEAPI(如JDBC、JavaMail、RPC等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。

  7. Java源码经典学习范例
    Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

Spring体系结构

Spring框架学习第一天_第1张图片

初识IOC

介绍

**控制反转(Inverse Of Control)**不是什么技术,而是一种设计思想。它的目的是指导我们设计出更加松耦合的程序
控制:在java中指的是对象的控制权限(创建、销毁)

反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到 由Spring容器控制

环境搭建

在IDEA中创建一个empty project,创建maven的java模块,导入Spring的架包

版本一:原始版本

存在的问题:service层和dao层代码产生了耦合,且每次调用方法时,都会创建一个新的dao对象。

版本二:工厂解耦

我们需要在项目中 定义BeanFactory + xml解析,实现各层代码之间解耦合

public class BeanFactory {

    public static Object getBean(String id) {
        Object object = null;
        try {
            // 1.通过类加载器读取 beans.xml
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
            // 2.创建dom4j核心解析器对象
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(in);
            // 3.编写xpath表达式
            // String xpath = "//bean[@id='userDao']";
            String xpath = "//bean[@id='" + id + "']";
            // 4.获取指定id的标签对象
            Element element = (Element) document.selectSingleNode(xpath);
            // 5.获取全限定名
            String className = element.attributeValue("class");
            // 6.通过反射创建对象实例
            object = Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 7.返回对象实例
        return object;
    }
}

版本三:工厂优化

使用单例模式

public class BeanFactory {

    // 声明存储对象的容器(map集合)
    private static Map<String, Object> ioc = new HashMap<>();

    // 静态代码块,初始化ioc容器
    static {
        String id = null;
        String className = null;
        Object object = null;
        try {
            // 1.通过类加载器读取 beans.xml
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
            // 2.创建dom4j核心解析器对象
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(in);
            // 3.编写xpath表达式
            String xpath = "//bean";
            // 4.获取所有的bean标签对象
            List<Element> list = document.selectNodes(xpath);
            // 5.遍历集合,创建对象实例,设置到ioc容器中
            for (Element element : list) {
                id = element.attributeValue("id");
                className = element.attributeValue("class");
                object = Class.forName(className).newInstance();
                // 设置到map集合
                ioc.put(id, object);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 从ioc容器中获取指定id的对象实例
    public static Object getBean(String id) {
        return ioc.get(id);
    }
}

对象的创建由原来的 使用 new关键字在类中主动创建 变成了 从工厂中获取, 而对象的创建过程由工厂内部来实现, 而这个工厂就是 Spring的IOC容器, 也就是以后我们的对象不再自己创建,而是直接向Spring要, 这种思想就是IOC,ioc目的:松耦合…,可以简单的认为就是一个map集合(ioc容器)

Spring快速入门

代码实现

导入相关坐标

Spring框架学习第一天_第2张图片

编写UserDao接口和实现类

package cn.itcast.dao.impl;

import cn.itcast.dao.UserDao;

public class UserDaoImpl implements UserDao {

    public UserDaoImpl() {
        System.out.println("UserDaoImpl创建了");

    }

    @Override
    public void save() {
        System.out.println("UserDao保存了");

    }

    //创建了
    public void chuangjian() {
        System.out.println("对象创建执行方法");
    }

    //销毁
    public void xiaohui() {
        System.out.println("对象销毁执行方法");
    }
}

package cn.itcast.dao;

public interface UserDao {
    void save();

}

创建spring的核心配置文件,导入约束(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

编写bean标签(id、class)

在这里插入图片描述

测试(模拟service层)

public class UserTest {

    // spring的快速入门
    @Test
    public void test01() throws Exception {
        // 1.通过spring的api读取配置文件
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 2.获取指定id的对象实例
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.save();
    }
}

Spring相关API

两个接口

  • BeanFactory
    介绍:
    这是IOC容器的顶级接口 它定义了IOC的最基础的功能, 但是其功能比较简单,一般面向Spring自身使用
    特点:
    在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化[用的时候再创建]
    懒汉设计

  • ApplicationContext
    介绍:
    这是在BeanFactory基础上衍生出的接口,它扩展了BeanFactory的功能,一般面向程序员使用
    特点:
    在容器启动时,一次性创建并加载了所有的Bean [初始化的时候全创建好]
    恶汉设计

  • 小结:上面两种方式创建的对象都是单例, 只是创建对象的时机不同

三个实现类

  • ClassPathXmlApplicationContext
    功能:
    读取类路径(classpath)下的xml配置文件

  • FileSystemXmlApplicationContext
    功能:
    读取本地磁盘下的xml配置文件

  • AnnotationConfigApplicationContext
    功能:
    读取java配置类加载配置

一个方法

  • public Object getBean(String name) throws BeansException;
    功能:
    通过指定id获取对象的实例,需要手动强转

  • public T getBean(Class requiredType);
    功能:
    通过指定类型获取对象的实例,不需要强转

  • public T getBean(String name, Class requiredType);
    功能:
    通过指定id和类型获取对象的实例

小结

ApplicationContext app = new ClasspathXmlApplicationContext(“xml文件”);
app.getBean(“id”);
app.getBean(Class);

Spring配置文件

Bean标签基本配置

基本配置

  <!--
        bean标签的二个基本属性
            id:在ioc容器的唯一标识
            class:创建对象实例的全限定名
    -->
    <bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl"></bean>

作用范围

  <!--
        bean标签还有一个属性scope属性:声明此对象的作用范围
            singleton:单例对象(默认)
                何时创建?
                    ioc容器初始化时,创建对象
                对象运行?
                    只要ioc容器在,对象就一直活着....
                何时销毁?
                    ioc容器关闭时,销毁对象
            prototype:多例对象
                何时创建?
                    在调用getBean()方法时,创建
                对象运行?
                    一直使用就一直活着
                何时销毁?
                    当对象不再使用后,根据JVM GC机制垃圾回收
    -->
    <bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl" scope="prototype"></bean>

Spring创建对象实例的三种方式

无参构造方法实例化【重点】

在企业开发时,所有的类必须提供无参构造方法.,如果没有无参构造,就会报错

工厂静态方法实例化【了解】

依赖的jar包中有个A类,A类中有个静态方法m1,m1方法的返回值是一个B对象。如果我们频繁使用B对象,此时我们可以将B对象的创建权交给spring的IOC容器,以后我们在使用B对象时,无需调用A类中的m1方法,直接从IOC容器获得

/*
    工厂静态方法实例化对象
 */
public class StaticFactoryBean {

    public static UserDao createUserDao() {
        return new UserDaoImpl();
    }

    // 传统方式,自己通过工厂获取对象...
    public static void main(String[] args) {
        UserDao userDao = StaticFactoryBean.createUserDao();
    }
}

工厂普通方法实例化【了解】

依赖的jar包中有个A类,A类中有个普通方法m1,m1方法的返回值是一个B对象。如果我们频繁使用B对象,此时我们可以将B对象的创建权交给spring的IOC容器,以后我们在使用B对象时,无需调用A类中的m1方法,直接从IOC容器获得

/*
    工厂普通方法实例化对象
 */
public class DynamicFactoryBean {

    public UserDao createUserDao() {
        return new UserDaoImpl();
    }


    // 传统方式,自己通过工厂获取对象...
    public static void main(String[] args) {
        // 1.创建工厂对象
        DynamicFactoryBean dynamicFactoryBean = new DynamicFactoryBean();
        // 2.创建UserDao对象
        UserDao userDao = dynamicFactoryBean.createUserDao();
    }
}

Bean依赖注入

概述

依赖注入(Dependency Injection, DI) 它是 Spring 框架核心 IOC 的具体实

其实就是给对象中的属性赋值的过程,通过spring完成依赖注入
Spring框架学习第一天_第3张图片

环境搭建

在pom文件中添加依赖管理和JDK插件以及Spring的JAR包

Bean依赖注入方式

构造方法

Spring框架学习第一天_第4张图片

    <!--
        构造方法注入: <constructor-arg> 子标签
            版本一:
                name:构造方法参数名称
                value:简单数据类型(String、intdouble...)
                ref:引用数据类型(从ioc容器中获取的对象)
            版本二:
                index:构造方法参数索引
                type:该索引对应的java类型(全限定名)
                value:简单数据类型(String、intdouble...)
                ref:引用数据类型(从ioc容器中获取的对象)
    -->
    <bean id="userService" class="cn.itcast.service.impl.UserServiceImpl">
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
        <!--<constructor-arg index="0" type="cn.itcast.dao.UserDao"  ref="userDao"></constructor-arg>-->
    </bean>

set方法【重点】

Spring框架学习第一天_第5张图片

  <!--将userDao交给ioc容器-->
    <bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl"></bean>  

    <!--
            set方法注入:<property> 子标签
                name:set方法的属性名  setUserDao()  -> UserDao -> userDao
                value:简单数据类型(String、intdouble...)
                ref:引用数据类型(从ioc容器中获取的对象)
    -->
    <bean id="userService" class="cn.itcast.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>

P命名空间注入

P命名空间注入底层(本质)使用的也是set方法注入,只是在上着的基础上进行简化
Spring框架学习第一天_第6张图片

Bean依赖注入的数据类型

简单数据类型

Spring框架学习第一天_第7张图片

引用数据类型

依赖注入的三种方式即为引用数据类型

集合数据类型

单例集合

list、set、array

    <!--
        di 注入单列集合类型
            需要在 <property>标签中
                list集合  使用子标签  <list>
                    <value> 简单数据类型
                    <ref>   引用数据类型(对象在ioc容器中)

              set集合    使用子标签 <set>
                    <value> 简单数据类型
                    <ref>   引用数据类型(对象在ioc容器中)

             array数组   使用子标签<array>
                    <value> 简单数据类型
                    <ref>   引用数据类型(对象在ioc容器中)
    -->
    <bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl">
        <property name="list">
            <list>
                <value>石榴姐</value>
                <value>冬香</value>
                <ref bean="user"></ref>
            </list>
        </property>

        <property name="set">
            <set>
                <value>秋香</value>
                <value>马冬梅</value>
                <ref bean="user"></ref>
            </set>
        </property>

        <property name="array">
            <array>
                <value>国际峰</value>
                <value>小绵羊</value>
                <ref bean="user"></ref>
            </array>
        </property>
    </bean>

双列集合

<!--
           di 注入双列集合类型
              需要在 <property>标签中
                map集合 使用子标签<map>
                     <entry key="" value="简单数据类型"  |  value-ref="引用数据类型(对象ioc中)"  ></entry>
               properties集合 使用子标签 <props>
                     <prop key="" >value</prop>

    -->
<bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl">
    <property name="map">
        <map>
            <entry key="k1" value="v1"></entry>
            <entry key="k2" value="v2"></entry>
            <entry key="u1" value-ref="user"></entry>
        </map>
    </property>

    <property name="props">
        <props>
            <prop key="k1" >v1</prop>
            <prop key="k2" >v2</prop>
            <prop key="k3" >v3</prop>
        </props>
    </property>
</bean>

map、properties

配置文件模块化

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,也就是所谓的配置文件模块化

并列加载

Spring框架学习第一天_第8张图片

主从配置【重点】

Spring框架学习第一天_第9张图片
注意:
1.在同一个xml中 bean标签的 id不能重复…
2.在多个模块中的xml中,bean标签id重复虽然不会报错,但是后加载的会覆盖先加载的…

你可能感兴趣的:(Spring框架学习,spring,java,编程语言,ioc,大数据)