spring学习第一天

200 阅读4分钟

spring

spring概述

1 spring是什么

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

2 spring的两大核心

Core Container 核心容器 IOC

单例 只创建一次 类成员只初始化一次

多例 对象被创建多次 执行效率没有单例对象高

IOC

创建对象的权利交给框架。包含依赖注入DI和依赖查找。

使用Spring的IOC解决程序耦合

基于XML的配置

1 新建bean.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 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中       id 属性:对象的唯一标识。       class 属性:指定要创建对象的全限定类名 --> 
<!-- 配置 service -->    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> </bean> 
<!-- 配置 dao --> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>

public static void main(String[] args) {   

// 1.使用 ApplicationContext 接口,就是在获取 spring 容器  

 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");  
 //2.根据 bean 的 id 获取对象   
IAccountService aService = (IAccountService) ac.getBean("accountService");  
 System.out.println(aService); 
  IAccountDao aDao = (IAccountDao) ac.getBean("accountDao");   System.out.println(aDao); 
 } 

基于XML的IOC细节

1 BeanFactory和 ApplicationContext 的区别

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

ApplicationContext 是它的子接口。

BeanFactory 和 ApplicationContext 的区别: 创建对象的时间点不一样。

ApplicationContext:单例对象创建 实际开发采用 构建核心容器是创建对象采取的思想是 立即加载的方式,只要一读取完马上创建配置文件中的配置对象。

只要一读取配置文件,默认情况下就会创建对象。

BeanFactory:多例对象使用

构建核心容器是创建对象采取的思想是 延迟加载的方式,什么时候根据ID获取对象什么时候创建对象 什么使用什么时候创建对象。

2 ApplicationContext 接口的实现类

ClassPathXmlApplicationContext: 可以加载类路径下的配置文件 要求配置文件必须在类路径下 不在的加载不了 实际开发使用

FileSystemXmlApplicationContext: 可以加载磁盘任意路径下的配置路径 必须有访问权限

AnnotationConfigApplicationContext: 用于读取注解创建容器

IOC 中 bean 标签和管理对象细节

创建bean的三种方式

1 第一种方式 使用默认构造函数创建在spring的配置文件使用bean标签 配以ID和class属性 且没有其他的标签 采用默认的构造函数创建bean对象如果没有默认的构造函数则对象不能创建

<bean id="accountService"class="com.service.impl.AccountServiceImpl"></bean>

2

<!--    第二种方式 使用普通工厂中的方法创建对象 (使用某个类中的方法创建对象并存入spring容器)-->
<!--    <bean id="instanceFactory" class="com.factory.InstanceFactory"></bean>-->
<!--    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountServiceInterface"></bean>-->

// 模拟工厂类 该类可能存在于jar包 无法修改源码来提供默认构造函数
public class InstanceFactory {

public AccountServiceInterface getAccountServiceInterface() {
    return new AccountServiceImpl();
}
}

3

<!--    第三个方式 使用静态工厂中的静态方法创建对象 使用某个类中的静态方法创建对象 并存入spring容器-->
<!--    <bean id="accountService" class="com.factory.StaticFactory" factory-method="getAccountServiceInterface"></bean>-->

public class StaticFactory {

public static AccountServiceInterface getAccountServiceInterface() {
    return new AccountServiceImpl();
}
}

bean的作用范围调整

<!--    bean的作用范围调整

    scope属性 用于指定bean的作用范围
    取值 singleton 单例 默认值              常用
         prototype 多例                    常用
         request   作用于web应用的请求范围
         session   作用于web应用的会话范围
         global-session 作用于集群环境的会话范围(全局会话范围)当不是集群环境就是session
	-->

<!--    <bean id="accountService" class="com.service.impl.AccountServiceImpl" scope="prototype"></bean>-->

负载均衡 global-session含义

bean对象的生命周期

<!--    bean对象的生命周期
    单例对象
        出生 当容器创建时对象出生
        活着 容器还在对象一直存在
        死亡 容器销毁 对象销毁
        总结 单例对象的生命周期和容器相同
    多例对象
        出生 当使用对象是spring框架创建
        活着 对象使用过程中一直存在
        死亡 对象长时间不用且没有别的对象引用 Java垃圾回收器回收
	-->

<bean id="accountService" class="com.service.impl.AccountServiceImpl" scope="prototype" init-method="init" destroy-method="destroy">

</bean>

spring 的依赖注入

依赖注入:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。 那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。 简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

<!--  Spring的依赖注入
  IOC的作用 降低程序间的耦合

  依赖关系管理
  交给spring来维护
  在当前类需要用到其他类的对象 由spring为我们提供 我们只需在配置文件中说明
  依赖关系的维护:
  就是依赖注入

  依赖注入:
  能注入的数据:基本类型和String
  其他的bean类型(配置文件中或者注解配置过的bean)
  复杂类型/集合类型

  注入的方式:
  第一种:使用构造函数
  第二种:使用set方法
  第三种:使用注解-->

构造函数注入

<!--    构造函数注入:                  很少使用
    使用标签:  constructor-arg
    出现的位置 bean标签内部
    标签属性:
        type 用于指定要注入的数据的数据类型 该数据类型也是构造函数中某个或者某些参数类型
        index 用于指定要注入的数据给构造函数在指定索引位置参数赋值。索引的位置从0开始
        name 用于指定给构造函数中指定名称的参数赋值                    常用的
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++用于指定给构造函数中参数赋值
        ref     用于指定其他bean类型数据。指的是spring的IOC核心容器中出现过得bean对象
        value 用于给基本类型和string类型的数据
   优势:
   获取bean对象注入数据是必须的操作否则无法创建成功。

   劣势:
   改变bean对象实例化方式 使创建对象如果用不到这些数据也必须提供
		-->	

<bean id="accountService" class="com.service.impl.AccountServiceImpl">
    <constructor-arg name="name" value="test"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
    <constructor-arg name="date" ref="now"></constructor-arg>
</bean>

<!--    配置日期对象-->
<bean id="now" class="java.util.Date"></bean>


// 账户的业务层实现类
public class AccountServiceImpl implements AccountServiceInterface {

// 经常变化的数据 并不适用于注入的方式
private String name;
private Integer age;
private Date date;

public AccountServiceImpl(String name,
                          Integer age,
                          Date date) {
    this.age = age;
    this.date = date;
    this.name = name;
}
public void saveAccount() {
    System.out.println("执行"+age+date+name);
}
}

setter方法

<!--    setter方法                            常用、、、、、、、、、、、、、、、、
    涉及的标签:property
    位置:bean标签内部
    标签属性:
        name 用于指定注入时所调用的sett方法名称
        ref     用于指定其他bean类型数据。指的是spring的IOC核心容器中出现过得bean对象
        value 用于给基本类型和string类型的数据

   优势:
   创建对象时没有明确的限制,可以直接使用默认构造函数。


   劣势:
   如果某个成员必须有值,则set方法无法保证一定注入.(获取对象可能set方法没有执行)
	-->

<bean id="accountService2" class="com.service.impl.AccountServiceImpl2">
    <property name="userName" value="test"></property>
    <property name="age" value="11"></property>
    <property name="date" ref="now"></property>
</bean>

public class AccountServiceImpl2 implements AccountServiceInterface  {

// 经常变化的数据 并不适用于注入的方式
private String name;
private Integer age;
private Date date;

public void setUserName(String name) {
    this.name = name;
}

public void setAge(Integer age) {
    this.age = age;
}

public void setDate(Date date) {
    this.date = date;
}

public void saveAccount() {
    System.out.println("执行"+age+date+name);
}
}

复杂/集合类型注入

<!--   复杂/集合类型注入
   给list结构集合的标签
   list Array set
   给map结构集合的标签
   map props
   结构相同 标签可以互换
	-->

<bean id="accountService3" class="com.service.impl.AccountServiceImpl3">
    <property name="myStr">
        <array>
    <value>AAA</value>
    <value>BBB</value>
    </array>
    </property>
    <property name="myList">
        <list>
            <value>AAA</value>
            <value>BBB</value>
        </list>
    </property>
    <property name="mySet">
        <set>
            <value>AAA</value>
            <value>BBB</value>
        </set>
    </property>
    <property name="myMap">
        <map>
            <entry key="AAA" value="aaaa"></entry>
            <entry key="BBBB"><value>bbbbb</value></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="eeeee">ffffff</prop>
        </props>
    </property>
</bean>

public class AccountServiceImpl3 implements AccountServiceInterface {

private String[] myStr;
private List<String> myList;
private Set<String> mySet;
private Map<String, String> myMap;
private Properties properties;

public void setMyStr(String[] myStr) {
    this.myStr = myStr;
}

public void setMyList(List<String> myList) {
    this.myList = myList;
}

public void setMySet(Set<String> mySet) {
    this.mySet = mySet;
}

public void setMyMap(Map<String, String> myMap) {
    this.myMap = myMap;
}

public void setProperties(Properties properties) {
    this.properties = properties;
}

public void saveAccount() {
    System.out.println(Arrays.toString(myStr));
    System.out.println(myList);
    System.out.println(myMap);
    System.out.println(mySet);
    System.out.println(properties);
}
}