Spring学习一-Spring概述、初识 IOC

1、Spring概述

1.1、Spring 是什么

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多 著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。

1.2、Spring 的发展历程

  • 1997 年 IBM 提出了 EJB 的思想

  • 1998 年,SUN 制定开发标准规范 EJB1.0 1999 年,EJB1.1 发布

  • 2001 年,EJB2.0 发布

  • 2003 年,EJB2.1 发布

  • 2006 年,EJB3.0 发布

    Rod Johnson(spring之父)

Expert One-to-One J2EE Design and Development(2002) 阐述了 J2EE 使用 EJB 开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB(2004) 阐述了 J2EE 开发不使用 EJB 的解决方式(Spring 雏形)

  • 2017年9月份发布了spring的最新版本spring 5.0通用版(GA)

1.3、Spring 的优势

  • 方便解耦,简化开发
  • AOP 编程的支持
  • 声明式事务的支持
  • 方便程序的测试
  • 方便集成各种优秀框架
  • 降低 JavaEE API 的使用难度
  • Java 源码是经典学习范例

1.4、体系结构

在这里插入图片描述

2、IOC 的概念和作用

2.1、耦合性

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调 用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关 系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。

2.2、如何解决耦合性的思路

之前学习 jdbc 时,是通过反射来注册驱动的,代码如下:

Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串

这里使用了反射,在编译阶段可以正常编译成功,不会因为类中没有依赖驱动类而报错,但是这样又是一种硬编码的写法,在类中使用了常量。为了解决这个问题,可以将常量写入到配置文件中。

2.3、使用工厂模式进行解耦

  • 当应用启动时,就加载配置文件,读取配置
  • 根据配置,使用反射创建对象实例
  • 使用对象

2.4、控制反转

之前我们使用对象,哪里需要就在哪里创建,使用new;现在我们将对象的创建后放入到 map 中进行存储,即容器中。

2.4.1、配置文件

beans.properties

userService=com.wmding.mybean.service.impl.UserServiceImpl
helloSpring=com.wmding.HelloSpring

2.4.2、工厂

BeanFactory.java

package com.wmding.mybean.factory;


import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author 明月
 * @version 1.0
 * @date 2020-04-19 20:53
 * @description:
 */
public class BeanFactory {

    private static Properties properties;
    private static Map<String, Object> beans;

    static {

        properties = new Properties();
        try {
            beans = new HashMap<String, Object>();
            properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("beans.properties"));

            Enumeration<Object> keys = properties.keys();

            while (keys.hasMoreElements()) {
                String key = keys.nextElement().toString();
                String value = properties.getProperty(key);

                Object o = Class.forName(value).newInstance();
                beans.put(key, o);
            }

        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化错误");
        }

    }

    public static Object getBean(String classPath) {
        return beans.get(classPath);
    }

}

2.4.3、使用

public class Client {
    public static void main(String[] args) {
        //Test01();
        UserService userService = (UserService) BeanFactory.getBean("userService");
        userService.saveUser(new User("w", 99));
    }

    private static void Test01() {
        UserService userService = null;
        try {
            userService = (UserService) Class.forName("com.wmding.mybean.service.impl.UserServiceImpl").newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        userService.saveUser(new User("wmding", 23));
    }
}

之前获取对象是主动的,现在获取对象是从工厂要(工厂帮我们创建并保存到map容器中)是被动的。

这种被动的接收的方式获取对象的思想就是控制反转,就是 spring 框架的核心之一。

3、Spring 的 IOC 解决程序耦合

3.1、使用到的依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.2.1.RELEASE</version>
</dependency>

3.2、基于 XML 的配置创建 bean

beans.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">

    <bean id="user" class="com.wmding.mybean.bean.User">
        <property name="name" value="wmding"/>
        <property name="age" value="20"/>
    </bean>

</beans>
public class Client {

    /**
     * 获取 Spring 的 IOC 核心容器,并根据 id 获取对象
     *
     * ApplicationContext 的三个常用实现类
     *      ClassPathXmlApplicationContext:加载类路径下的配置文件,
     *      FileSystemXmlApplicationContext:加载磁盘下的任意路径下的配置文件,但是源码中会把路径的第一个/给去掉,导致在Mac,Linux下需要在路径开头多写一个/
     *      AnnotationConfigApplicationContext:它用于读取注解创建容器。
     * @param args
     */
    public static void main(String[] args) {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

        //ApplicationContext applicationContext = new FileSystemXmlApplicationContext("/"+"/Users/wmding/WorkSpaces/My/spring/src/main/resources/beans.xml");

        UserService userService = (UserService) applicationContext.getBean("userService");

        System.out.println(userService);

        userService.saveUser(new User("111",11));
    }
}

BeanFactory 和 ApplicationContext 的区别

BeanFactory 才是 Spring 容器中的顶层接口。 ApplicationContext 是它的子接口。

BeanFactory 和 ApplicationContext 的区别:

  • 创建对象的时间点不一样。ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。 BeanFactory:什么使用什么时候创建对象。

3.3、IOC 中 bean 标签的使用

3.3.1、bean 标签

  • 作用:

    • 用于配置对象让 spring 来创建的。
    • 默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功.
  • 属性:

    • id:给对象在容器中提供一个唯一标识。用于获取对象。
    • class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
    • scope:指定对象的作用范围。
    • singleton :默认值,单例的.
    • prototype :多例的.
    • request:WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中.
    • session:WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中.
    • global-session:WEB项目中,应用在Portlet环境.如果没有Portlet环境那么 globalSession 相当于 session.
    • init-method:指定类中的初始化方法名称。
    • destroy-method:指定类中销毁方法名称。

3.3.2、bean的作用范围和生命周期

  • 单例对象:scope=“singleton”

生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。

  • 多例对象:scope=“prototype”

生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

3.3.3、实例化 bean 的三种方式

  • 使用默认构造函数
  • 静态工厂-使用静态工厂的方法创建对象
  • 实例工厂-使用实例工厂的方法创建对象
3.3.3.1、使用默认构造函数
<!--
第一种方式,使用默认无参构造函数
会根据默认无参构造函数来创建类对象,如果 bean 中没有默认无参构造函数,将会失败
-->
<bean id="userService" class="com.wmding.mybean.service.impl.UserServiceImpl"/>
3.3.3.2、实例工厂
<!--
第二种方式,使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入Spring容器中)   
-->
<bean id="beanFactory" class="com.wmding.ioc.factory.BeanFactory"/>
<bean id="userService" factory-bean="beanFactory" factory-method="getUserService"/>
public class BeanFactory {

    public UserService getUserService() {
        return new UserServiceImpl();
    }
}
3.3.3.3、静态工厂
<!--
第三种方式,使用工厂中的静态方法创建对象(使用某个类的静态方法创建对象,并存入Spring的容器中)
-->
<bean id="userService" class="com.wmding.ioc.factory.StaticBeanFactory" factory-method="getUserService"/>
public class StaticBeanFactory {

    public static UserService getUserService() {
        return new UserServiceImpl();
    }
}

3.4 Spring 的依赖注入

依赖注入:Dependency Injection。它是spring框架核心ioc的具体实现。

3.4.1、构造函数注入

<!--
需要类中有一个构造函数;
constructor-arg
  属性: 
  index:指定参数在构造函数参数列表的索引位置
  type:指定参数在构造函数中的数据类型
  name:指定参数在构造函数中的名称

  value:它能赋的值是基本数据类型和 String 类型
  ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
-->
<bean id="user2" class="com.wmding.mybean.bean.User">
  <constructor-arg name="name" value="wmding"></constructor-arg>
  <constructor-arg name="age" value="20"></constructor-arg>
</bean>

3.4.2、set 方法注入

<!--
提供set方法;
property
  属性:
  name:找的是类中 set 方法后面的部分 
  ref:给属性赋值是其他 bean 类型的 
  value:给属性赋值是基本数据类型和 string 类型的
-->

<bean id="user" class="com.wmding.mybean.bean.User">
  <property name="name" value="wmding"/>
  <property name="age" value="20"/>
</bean>

3.4.3、注入集合属性

<bean id="user3" class="com.wmding.mybean.bean.User">
  <property name="name" value="wmding"/>
  <property name="age" value="20"/>
  <property name="map">
    <props>
    <prop key="map1">map1</prop>
    <prop key="map2">map3</prop>
    </props>
   </property>
	<property name="list">
    <list>
      <value>111</value>
      <value>222</value>
      <value>333</value>
    </list>
   </property>
</bean>
发布了57 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wmdkanh/article/details/105669986