Spring(IoC的xml配置)

一、Spring概述

1、Spring的优势

Spring 出现是为了解决JavaEE 实际问题:

  1. 方便解耦,简化开发

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

  1. AOP编程的支持

       通过Spring的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP(面向对象)实现的功能可以通过AOP轻松应付。

  1. 声明式事务的支持

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

  1. 方便程序的测试

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

  1. 方便集成各种优秀框架

       Spring可以降低各种框架的使用难度,提供了对各种优秀框架Struts、Hibernate、Hessian(远程通讯,类似于webService)、Quartz(定时任务)等的直接支持。

  1. 降低JavaEE API的使用难度

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

 

2、Spring的核心

IoC(Inverse of Control 控制反转): 将对象创建权利交给Spring工厂进行管理。

AOP(Aspect Oriented Programming 面向切面编程),基于动态代理的功能增强方式。

 

 

二、IoC的概念和作用

1、程序的耦合和解耦(理解)

 

1.1 什么是程序的耦合

我们在开发中,会写很多的类,而有些类之间不可避免的产生依赖关系,这种依赖关系称之为耦合。

代码中的耦合关系不利于组件式开发:

 

1.2 解决程序耦合的思路

        使用配置文件配置。

 

 

 

三、使用Spring的Ioc解耦

 

3.1案例的前期准备

案例是:账户的业务层和持久层的依赖关系解决。

在开始 spring 的配置之前,我们要先准备一下环境。

 

官网:http://spring.io/ 

下载地址: http://repo.springsource.org/libs-release-local/org/springframework/spring

我们上课使用的版本是spring4.3.13

解压:(Spring 目录结构:) :

 

步骤一:创建工程

 

 

步骤二:业务层接口和实现类

 

接口:

public interface IAccountService {

 

    /**

     * 模拟保存账户

     */

    void saveAccount();

}

 

实现类:

public class AccountServiceImpl implements IAccountService {

    //手动初始化

    private IAccountDao accountDao = new AccountDaoImpl();

    @Override

    public void saveAccount() {

        accountDao.saveAccount();

    }

}

 

步骤三:持久层(Dao)接口和实现类

 

接口:

public interface IAccountDao {

    void saveAccount();

}

实现类:

public class AccountDaoImpl implements IAccountDao {

    @Override

    public void saveAccount() {

        System.out.println("保存账户");

    }

}

 

 

 

3.2 Spring 基于xml的解耦方案

步骤一:创建配置文件模板

 

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>

 

创建模板:

 

步骤二:创建配置文件

 

之前我们模拟的控制反转的实现过程:

                    IoC底层实现:工厂(设计模式)+反射(机制) + 配置文件                    

在spring中,工厂和反射机制由框架完成,我们只需要编写配置文件即可。

 

在resources下创建:applicationContext.xml

如果创建的配置文件报红,刷新maven即可。

 

 

步骤三:导入依赖

 

 <dependencies>

        <!--IOC相关依赖-->

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-context</artifactId>

            <version>5.0.6.RELEASE</version>

        </dependency>

   </dependencies>

 

 

步骤四:将dao和service的实现类装配到容器中

 

步骤五: 从容器中获取daoservice实现类

将web层代码修改如下:

 

 

3.3  Spring基于 XML IOC 细节[掌握]

 

3.3.1  spring 中工厂的类结构图

 

3.3.1.1  BeanFactory ApplicationContext 的区别

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

ApplicationContext 是它的子接口。

BeanFactory ApplicationContext 的区别:  

创建对象的时间点不一样。  

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

            BeanFactory:什么使用什么时候创建对象。

 

Beanfactory的用法:

     BeanFactory ac = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

 

 

3.3.1.2   ApplicationContext 接口的实现类

ClassPathXmlApplicationContext 

            它是从类的根路径下加载配置文件  推荐使用这种

FileSystemXmlApplicationContext: 

            它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

AnnotationConfigApplicationContext:

             当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

 

3.3.2.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:指定类中销毁方法名称(生命周期相关)。

 

2.3.2.2  bean的作用域

 

scope:指定对象的作用范围。   

* singleton :默认值,单例的.    作用范围就是整个应用

* prototype :多例的. 每次访问对象时,都会重新创建对象实例。

 

步骤一:创建ScopeBean

内容如下;

public class ScopeBean {

 

}

 

步骤二:装配ScopeBean

<!--装配scopeBean-->

<bean id="scopeBean" class="cn.itcast.bean.ScopeBean" scope="prototype"></bean>

 

步骤三:创建ClientScope

 

结果:

* singleton :默认值,单例的.    作用范围就是整个应用

* prototype :多例的. 每次访问对象时,都会重新创建对象实例。

 

 

3.3.2.3     bean 的生命周期 (记住

 

单例对象:scope="singleton"

                   一个应用只有一个对象的实例。它的作用范围就是整个应用

                   生命周期:

                            对象出生:当应用加载,创建容器时,对象就被创建了。

                            对象活着:只要容器在,对象一直活着。

                            对象死亡:当应用卸载,销毁容器(close)时,对象就被销毁了。

         多例对象:scope="prototype"

                  每次访问对象时,都会重新创建对象实例。

                   生命周期:

                            对象出生:当使用对象时,创建新的对象实例(getBean

                            对象活着:只要对象在使用中,就一直活着。

                      对象死亡:当对象长时间不用时,被java的垃圾回收器回收了。

 

步骤一:创建LifecycleBean

内容如下:

public class LifecycleBean {

 

    public LifecycleBean() {

        System.out.println("lifecycleBean被初始化了");

    }

 

    public void start(){

        System.out.println("初始化方法执行了");

    }

    public void end(){

        System.out.println("销毁方法执行了");

    }

}

 

步骤二:装配LifecycleBean

<!--装配lifecycleBean-->

<bean id="lifecycleBean" class="cn.itcast.bean.LifecycleBean" init-method="start" destroy-method="end" scope=" singleton"></bean>

 

步骤三:创建ClientLifecycle

public class ClientLifecycle {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        LifecycleBean lifecycleBean = (LifecycleBean) ac.getBean("lifecycleBean");

        ac.close();

    }

}

 

(单例)生命周期方法执行了:

 

 

步骤四:修改配置文件

 

<!--装配lifecycleBean-->

<bean id="lifecycleBean" class="cn.itcast.bean.LifecycleBean" init-method="start" destroy-method="end" scope=" prototype"></bean>

 

再次执行main方法发现,LifecycleBean被延迟加载了,并且只执行了初始化方法-start,没有执行销毁方法end.(垃圾回收站回收销毁)

 

 

3.3.2.4    实例化 Bean 的三种方式

第一种方式:使用默认无参构造函数创建对象

       在默认情况下:   它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败

 

第二种方式:使用静态工厂的方法创建对象  (一步)

        (1)使用工厂中的静态方法创建对象,并存入 spring 容器 

            id 属性:指定 bean 的 id,用于从容器中获取  

            class 属性:指定静态工厂的全限定类名  

            factory-method 属性:指定生产对象的静态方法

 

第三种方式:使用实例工厂的方法创建对象

        (1)先把工厂的创建交给 spring 来管理。  

        (2)然后再使用工厂的 bean 来调用里面的方法  

            factory-bean 属性:用于指定实例工厂 bean id   

            factory-method 属性:用于指定实例工厂中创建对象的方法。

 

1、默认无参构造创建对象

<!-- service实现类装配到容器中 -->

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

 

2、静态工厂方法创建对象

第一步:创建静态工厂

/**

 * 假设service的实现类是由工厂中的静态方法创建的

 */

public class StaticFactory {

    public static IAccountService createAccountService(){

        return new AccountServiceImpl();

    }

}

第二步:编写配置文件

将之前的servicebean注释掉重新装配一个即可

factory-method 属性:指定生产对象的静态方法

<!-- 通过静态工厂方法创建对象并装配到容器中 -->

<bean id="accountService" class="cn.itcast.utils.StaticFactory" factory-method="createAccountService"></bean>

 

 

第三步:测试

public class ClientStatic {

    public static void main(String[] args) {

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

        IAccountService accountService = (IAccountService) ac.getBean("accountService");

            System.out.println(accountService);

    }

}

 

3、 实例工厂方法创建对象

 

第一步:创建实例工厂

/**

 * 假设service的实现类是由一个工厂的非静态方法创建的

 * @author zhang

 *

 */

public class InstanceFactory {

    public IAccountService createAccountService(){

 

        return new AccountServiceImpl();

    }

}

 

第二步:编写配置文件

将之前的service的bean注释掉重新装配一个即可

factory-bean 属性:用于指定实例工厂 bean id   

factory-method 属性:用于指定实例工厂中创建对象的方法。

<!-- 将实例工厂装配到容器中 -->

<bean id="instanceFactory" class="cn.itcast.utils.InstanceFactory"></bean>

 

<!-- 调用实例工厂中的非静态方法创建对象 -->

<bean id="accountService" factory-bean="instanceFactory" factory-method="createAccountService"></bean>

第三步:测试

public class ClientInstance {

    public static void main(String[] args) {

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

        IAccountService accountService = (IAccountService) ac.getBean("accountService");

        System.out.println(accountService);

    }

}

 

 

 

3.3.3  Spring的依赖注入

 

依赖注入的概念

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

       我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。

        那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。

        简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

 

        

1、 构造方法注入属性

 

顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们硬编码的,而是通过配置的方式,让spring框架来为我们注入。

要求:

  1. bean对象需要创建有参数的构造方法

  2. 在配置文件中通过constructor-arg标签注入属性

 

步骤一:创建AccountServiceImpl2

 

创建一个AccountServiceImpl2并添加有参构造函数

 

步骤二:编写配置文件

 

 

 

 

 

 

步骤三:创建Client2测试

 

 

2、set方法注入

顾名思义,就是使用类中的set方法,给成员变量赋值。注意,赋值的操作不是我们硬编码的,而是通过配置的方式,让spring框架来为我们注入。

要求:

  1. 有setter方法

  2. 在配置文件中通过proprety标签注入属性

步骤一:创建AccountServiceImpl3( 提供属性的set方法

 

步骤二:编写配置文件

 

步骤三:创建Client3测试

 

 

 

3、 P名称空间注入

       此种方式是通过在 xml中导入 p名称空间,使用 p:propertyName属性 来注入数据,它的本质仍然是调用类中的 set 方法实现注入功能

要求:

  1. 有setter方法

  2. 在applicationContext.xml 配置文件中加入xmlns:p="http://www.springframework.org/schema/p"

  3. 使用 p:propertyName属性

步骤一:创建AccountServiceImpl4(提供属性的set方法

步骤二:编写配置文件

xmlns:p="http://www.springframework.org/schema/p"

步骤三:创建Client4测试

4、 复杂类型的注入

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。 我们这里介绍注入:

数组,List,Set,Map,Properties(资源文件格式 jdbc.properties)。

步骤一:创建AccountServiceImpl5(提供set方法)

步骤二:编写配置文件

步骤三:创建Client5测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值