Spring——day02

今日目标

  • 掌握IOC/DI配置管理第三方bean

  • 掌握IOC/DI的注解开发

  • 掌握IOC/DI注解管理第三方bean

  • 完成Spring与Mybatis及Junit的整合开发

1、IOC/DI配置管理第三方bean

 前面所讲的知识点都是基于我们自己写的类,现在如果有需求让我们去管理第三方jar包中的类,该如何管理?

1.1 案例:数据源对象管理

 在这一节中,我们将通过一个案例来学习下对于第三方bean该如何进行配置管理。

以后我们会用到很多第三方的bean,本次案例将使用咱们前面提到过的数据源Druid(德鲁伊)C3P0来配置学习下。

1.1.1 环境准备

学习之前,先来准备下案例环境:

  • 创建一个Maven项目

  • pom.xml添加依赖
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>
  • resources下添加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>
  • 编写一个运行类App

    public class App {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        }
    }

1.1.2 思路分析

在上述环境下,我们来对数据源进行配置管理,先来分析下思路:

需求:使用Spring的IOC容器来管理Druid连接池对象

1.使用第三方的技术,需要在pom.xml添加依赖

2.在配置文件中将【第三方的类】制作成一个bean,让IOC容器进行管理

3.数据库连接需要基础的四要素驱动连接用户名密码,【如何注入】到对应的bean中

4.从IOC容器中获取对应的bean对象,将其打印到控制台查看结果

思考:

  • 第三方的类指的是什么?

  • 如何注入数据库连接四要素?

1.1.3 实现Druid管理

带着这两个问题,把下面的案例实现下:

步骤1:导入druid的依赖

pom.xml中添加依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

步骤2:配置第三方bean

在applicationContext.xml配置文件中添加DruidDataSource的配置

<?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">
    <!--管理DruidDataSource对象-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>

说明:

  • driverClassName:数据库驱动

  • url:数据库连接地址

  • username:数据库连接用户名

  • password:数据库连接密码

  • 数据库连接的四要素要和自己使用的数据库信息一致。

步骤3:从IOC容器中获取对应的bean对象

public class App {
    public static void main(String[] args) {
       ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
       DataSource dataSource = (DataSource) ctx.getBean("dataSource");
       System.out.println(dataSource);
    }
}

步骤4:运行程序

打印如下结果: 说明第三方bean对象已经被spring的IOC容器进行管理

 做完案例后,我们可以将刚才思考的两个问题答案说下:

  • 第三方的类指的是什么?

    DruidDataSource
  • 如何注入数据库连接四要素?

    setter注入

1.1.4 实现C3P0管理

完成了DruidDataSource的管理,接下来我们再来加深下练习,这次我们来管理C3P0数据源,具体的实现步骤是什么呢?

需求:使用Spring的IOC容器来管理C3P0连接池对象

实现方案和上面基本一致,重点要关注管理的是哪个bean对象?

步骤1:导入C3P0的依赖

pom.xml中添加依赖

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

对于新的技术,不知道具体的坐标该如何查找?

  • 直接百度搜索

  • 从mvn的仓库https://mvnrepository.com/中进行搜索

     步骤2:配置第三方bean

在applicationContext.xml配置文件中添加配置

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="maxPoolSize" value="1000"/>
</bean>

==注意:==

  • ComboPooledDataSource的属性是通过setter方式进行注入

  • 想注入属性就需要在ComboPooledDataSource类或其上层类中有提供属性对应的setter方法

  • C3P0的四个属性和Druid的四个属性是不一样的

步骤3:运行程序

程序会报错,错误如下

报的错为==ClassNotFoundException==,翻译出来是类没有发现的异常,具体的类为com.mysql.jdbc.Driver。错误的原因是缺少mysql的驱动包。

分析出错误的原因,具体的解决方案就比较简单,只需要在pom.xml把驱动包引入即可。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

添加完mysql的驱动包以后,再次运行App,就可以打印出结果:

 注意:

  • 数据连接池在配置属性的时候,除了可以注入数据库连接四要素外还可以配置很多其他的属性,具体都有哪些属性用到的时候再去查,一般配置基础的四个,其他都有自己的默认值

  • Druid和C3P0在没有导入mysql驱动包的前提下,一个没报错一个报错,说明Druid在初始化的时候没有去加载驱动,而C3P0刚好相反

  • Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会报找不到驱动类的错误

 1.2 加载properties文件

上节中我们已经完成两个数据源druidC3P0的配置,但是其中包含了一些问题,我们来分析下:

  • 这两个数据源中都使用到了一些固定的常量如数据库连接四要素,把这些值写在Spring的配置文件中不利于后期维护

  • 需要将这些值提取到一个外部的properties配置文件中

  • Spring框架如何从配置文件中读取属性值来配置就是接下来要解决的问题。

问题提出来后,具体该如何实现?

1.2.1 第三方bean属性优化

1.2.1.1 实现思路

需求:将数据库连接四要素提取到properties配置文件,spring来加载配置信息并使用这些信息来完成属性注入。

1.在resources下创建一个jdbc.properties(文件的名称可以任意)

2.将数据库连接四要素配置到配置文件中

3.在Spring的配置文件中加载properties文件

4.使用加载到的值实现属性注入

其中第3,4步骤是需要大家重点关注,具体是如何实现。

1.2.1.2 实现步骤

步骤1:准备properties配置文件

resources下创建一个jdbc.properties文件,并添加对应的属性键值对

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root

步骤2:开启context命名空间

在applicationContext.xml中开context命名空间

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

步骤3:加载properties配置文件

在配置文件中使用context命名空间下的标签来加载properties配置文件

<context:property-placeholder location="jdbc.properties"/>

步骤4:完成属性注入

使用${key}来读取properties配置文件中的内容并完成属性注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:property-placeholder location="jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

至此,读取外部properties配置文件中的内容就已经完成。

1.2.2 读取单个属性

1.2.2.1 实现思路

对于上面的案例,效果不是很明显,我们可以换个案例来演示下:

需求:从properties配置文件中读取key为name的值,并将其注入到BookDao中并在save方法中进行打印。

1.在项目中添加BookDao和BookDaoImpl类

2.为BookDaoImpl添加一个name属性并提供setter方法

3.在jdbc.properties中添加数据注入到bookDao中打印方便查询结果

4.在applicationContext.xml添加配置完成配置文件加载、属性注入(${key})

1.2.2.2 实现步骤

步骤1:在项目中添对应的类

BookDao和BookDaoImpl类,并在BookDaoImpl类中添加name属性与setter方法

public interface BookDao {
    public void save();
}
​
public class BookDaoImpl implements BookDao {
    private String name;
​
    public void setName(String name) {
        this.name = name;
    }
​
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

步骤2:完成配置文件的读取与注入

在applicationContext.xml添加配置,bean的配置管理读取外部properties依赖注入:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:property-placeholder location="jdbc.properties"/>
    
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="name" value="${jdbc.driver}"/>
    </bean>
</beans>

步骤3:运行程序

在App类中,从IOC容器中获取bookDao对象,调用方法,查看值是否已经被获取到并打印控制台

public class App {
    public static void main(String[] args) throws Exception{
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
​
    }
}

 1.2.2.3 注意事项

至此,读取properties配置文件中的内容就已经完成,但是在使用的时候,有些注意事项:

  • 问题一:键值对的key为username引发的问题

    1.在properties中配置键值对的时候,如果key设置为username

    username=root666

    2.在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"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
        
        <context:property-placeholder location="jdbc.properties"/>
        
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
            <property name="name" value="${username}"/>
        </bean>
    </beans>

    3.运行后,在控制台打印的却不是root666,而是自己电脑的用户名

     4.出现问题的原因是<context:property-placeholder/>标签会加载系统的环境变量,而且环境变量的值会被优先加载,如何查看系统的环境变量?

    public static void main(String[] args) throws Exception{
        Map<String, String> env = System.getenv();
        System.out.println(env);
    }

    大家可以自行运行,在打印出来的结果中会有一个USERNAME=XXX[自己电脑的用户名称]

    5.解决方案

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
        
        <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
    </beans>

    system-properties-mode:设置为NEVER,表示不加载系统属性,就可以解决上述问题。

    当然还有一个解决方案就是避免使用username作为属性的key

  • 问题二:当有多个properties配置文件需要被加载,该如何配置?

    1.调整下配置文件的内容,在resources下添加jdbc.properties,jdbc2.properties,内容如下:

    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    jdbc.username=root
    jdbc.password=root

    jdbc2.properties

    username=root666

    2.修改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"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
        <!--方式一 -->
        <context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>
        <!--方式二-->
        <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>
        <!--方式三 -->
        <context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
        <!--方式四-->
        <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
    </beans>   

    说明:

    • 方式一:可以实现,如果配置文件多的话,每个都需要配置

    • 方式二:*.properties代表所有以properties结尾的文件都会被加载,可以解决方式一的问题,但是不标准

    • 方式三:标准的写法,classpath:代表的是从根路径下开始查找,但是只能查询当前项目的根路径

    • 方式四:不仅可以加载当前项目还可以加载当前项目所依赖的所有项目的根路径下的properties配置文件

1.2.3 加载properties文件小结

本节主要讲解的是properties配置文件的加载,需要掌握的内容有:

  • 如何开启context命名空间

  • 如何加载properties配置文件

    <context:property-placeholder location="" system-properties-mode="NEVER"/>
  • 如何在applicationContext.xml引入properties配置文件中的值

    ${key}

2、核心容器 

前面已经完成bean与依赖注入的相关知识学习,接下来我们主要学习的是IOC容器中的==核心容器==。

这里所说的核心容器,大家可以把它简单的理解为ApplicationContext,前面虽然已经用到过,但是并没有系统的学习,接下来咱们从以下几个问题入手来学习下容器的相关知识:

  • 如何创建容器?

  • 创建好容器后,如何从容器中获取bean对象?

  • 容器类的层次结构是什么?

  • BeanFactory是什么?

2.1 环境准备

在学习和解决上述问题之前,先来准备下案例环境:

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
  • resources下添加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">
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    </beans>
  • 添加BookDao和BookDaoImpl类

    public interface BookDao {
        public void save();
    }
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
  • 创建运行类App

    public class App {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }

最终创建好的项目结构如下:

2.2 容器

 2.2.1 容器的创建方式

案例中创建ApplicationContext的方式为:

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

这种方式翻译为:==类路径下的XML配置文件==

除了上面这种方式,Spring还提供了另外一种创建方式为:

ApplicationContext ctx = new FileSystemXmlApplicationContext
("applicationContext.xml");

这种方式翻译为:==文件系统下的XML配置文件==

使用这种方式,运行,会出现如下错误:

 从错误信息中能发现,这种方式是从项目路径下开始查找applicationContext.xml配置文件的,所以需要将其修改为:

ApplicationContext ctx = new FileSystemXmlApplicationContext
("D:\\workspace\\spring\\spring_10_container\\src\\
main\\resources\\applicationContext.xml"); 

说明:大家练习的时候,写自己的具体路径。

这种方式虽能实现,但是当项目的位置发生变化后,代码也需要跟着改,耦合度较高,不推荐使用。

2.2.2 Bean的三种获取方式

方式一,就是目前案例中获取的方式:

BookDao bookDao = (BookDao) ctx.getBean("bookDao");

这种方式存在的问题是每次获取的时候都需要进行类型转换,有没有更简单的方式呢?

方式二:

BookDao bookDao = ctx.getBean("bookDao",BookDao.class);

这种方式可以解决类型强转问题,但是参数又多加了一个,相对来说没有简化多少。

方式三:

BookDao bookDao = ctx.getBean(BookDao.class);

这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。

2.2.3 容器类层次结构

(1)在IDEA中双击shift,输入BeanFactory

 (2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系

 从图中可以看出,容器类也是从无到有根据需要一层层叠加上来的,大家重点理解下这种设计思想。

2.2.4 BeanFactory的使用

使用BeanFactory来创建IOC容器的具体实现方式为:

public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}

为了更好的看出BeanFactoryApplicationContext之间的区别,在BookDaoImpl添加如下构造函数:

public class BookDaoImpl implements BookDao {
    public BookDaoImpl() {
        System.out.println("constructor");
    }
    public void save() {
        System.out.println("book dao save ..." );
    }
}

如果不去获取bean对象,打印会发现:

  • BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建

  • ApplicationContext是立即加载,容器加载的时候就会创建bean对象

  • ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置

    <?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"  lazy-init="true"/>
    </beans>

小结

这一节中所讲的知识点包括:

  • 容器创建的两种方式

    • ClassPathXmlApplicationContext[掌握]

    • FileSystemXmlApplicationContext[知道即可]

  • 获取Bean的三种方式

    • getBean("名称"):需要类型转换

    • getBean("名称",类型.class):多了一个参数

    • getBean(类型.class):容器中不能有多个该类的bean对象

    上述三种方式,各有各的优缺点,用哪个都可以。

  • 容器类层次结构

    • 只需要知晓容器的最上级的父接口为 BeanFactory即可

  • BeanFactory

    • 使用BeanFactory创建的容器是延迟加载

    • 使用ApplicationContext创建的容器是立即加载

    • 具体BeanFactory如何创建只需要了解即可。

 2.3 核心容器总结

这节中没有新的知识点,只是对前面知识的一个大总结,共包含如下内容:

2.3.1 容器相关

  • BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载

  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能

  • ApplicationContext接口常用初始化类

    • ==ClassPathXmlApplicationContext(常用)==

    • FileSystemXmlApplicationContext

2.3.2 bean相关

 其实整个配置中最常用的就两个属性==id==和==class==。

把scope、init-method、destroy-method框起来的原因是,后面注解在讲解的时候还会用到,所以大家对这三个属性关注下。

2.3.3 依赖注入相关

 3、IOC/DI注解开发

Spring的IOC/DI对应的配置开发就已经讲解完成,但是使用起来相对来说还是比较复杂的,复杂的地方在==配置文件==。

前面咱们聊Spring的时候说过,Spring可以简化代码的开发,到现在并没有体会到。

所以Spring到底是如何简化代码开发的呢?

要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:

  • 2.0版开始支持注解

  • 2.5版注解功能趋于完善

  • 3.0版支持纯注解开发

关于注解开发,我们会讲解两块内容注解开发定义bean纯注解开发

注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解

 3.1 环境准备

在学习注解开发之前,先来准备下案例环境:

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
  • resources下添加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">
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    </beans>
  • 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类

    public interface BookDao {
        public void save();
    }
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
    public interface BookService {
        public void save();
    }
    ​
    public class BookServiceImpl implements BookService {
        public void save() {
            System.out.println("book service save ...");
        }
    }
  • 创建运行类App

    public class App {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }

最终创建好的项目结构如下:

 3.2 注解开发定义bean

在上述环境的基础上,我们来学一学Spring是如何通过注解实现bean的定义开发?

步骤1:删除原XML配置

将配置文件中的<bean>标签删除掉

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

步骤2:Dao上添加注解

在BookDaoImpl类上添加@Component注解

@Component("bookDao")
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}

注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。

XML与注解配置的对应关系:

步骤3:配置Spring的注解包扫描

为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

<?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">
    <context:component-scan base-package="com.itheima"/>
</beans>

说明:

component-scan

  • component:组件,Spring将管理的bean视作自己的一个组件

  • scan:扫描

base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

  • 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快

  • 包路径越少[如:com.itheima],扫描的范围越大速度越慢

  • 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。

步骤4:运行程序

运行App类查看打印结果

 步骤5:Service上添加注解

在BookServiceImpl类上也添加@Component交给Spring框架管理

@Component
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
​
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
​
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

步骤6:运行程序

在App类中,从IOC容器中获取BookServiceImpl对应的bean对象,打印

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //按类型获取bean
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

打印观察结果,两个bean对象都已经打印到控制台

 说明:

  • BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象

  • @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如

    BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
    System.out.println(bookService);

对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository

通过查看源码会发现:

 这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?

方便我们后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。

知识点1:@Component等

名称@Component/@Controller/@Service/@Repository
类型类注解
位置类定义上方
作用设置该类为spring管理的bean
属性value(默认):定义bean的id

 3.3 纯注解开发模式

上面已经可以使用注解来配置bean,但是依然有用到配置文件,在配置文件中对包进行了扫描,Spring在3.0版已经支持纯注解开发

  • Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道

具体如何实现?

3.3.1 思路分析

实现思路为:

  • 将配置文件applicationContext.xml删除掉,使用类来替换。

3.3.2 实现步骤

步骤1:创建配置类

创建一个配置类SpringConfig

public class SpringConfig {
}

步骤2:标识该类为配置类

在配置类上添加@Configuration注解,将其标识为一个配置类,替换applicationContext.xml

@Configuration
public class SpringConfig {
}

步骤3:用注解替换包扫描配置

在配置类上添加包扫描注解@ComponentScan替换<context:component-scan base-package=""/>

@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}

步骤4:创建运行类并执行

创建一个新的运行类AppForAnnotation

public class AppForAnnotation {
​
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

运行AppForAnnotation,可以看到两个对象依然被获取成功

 至此,纯注解开发的方式就已经完成了,主要内容包括:

  • Java类替换Spring核心配置文件

  • @Configuration注解用于设定当前类为配置类

  • @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

    @ComponentScan({com.itheima.service","com.itheima.dao"})
  • 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象

    //加载配置文件初始化容器
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    //加载配置类初始化容器
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

知识点1:@Configuration

名称@Configuration
类型类注解
位置类定义上方
作用设置该类为spring配置类
属性value(默认):定义bean的id

知识点2:@ComponentScan

名称@ComponentScan
类型类注解
位置类定义上方
作用设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性value(默认):扫描路径,此路径可以逐层向下扫描

小结:

这一节重点掌握的是使用注解完成Spring的bean管理,需要掌握的内容为:

  • 记住@Component、@Controller、@Service、@Repository这四个注解

  • applicationContext.xml中<context:component-san/>的作用是指定扫描包路径,注解为@ComponentScan

  • @Configuration标识该类为配置类,使用类替换applicationContext.xml文件

  • ClassPathXmlApplicationContext是加载XML配置文件

  • AnnotationConfigApplicationContext是加载配置类

 3.4 注解开发bean作用范围与生命周期管理

使用注解已经完成了bean的管理,接下来按照前面所学习的内容,将通过配置实现的内容都换成对应的注解实现,包含两部分内容:bean作用范围bean生命周期

3.4.1 环境准备

老规矩,学习之前先来准备环境:

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
  • 添加一个配置类SpringConfig

    @Configuration
    @ComponentScan("com.itheima")
    public class SpringConfig {
    }
  • 添加BookDao、BookDaoImpl类

    public interface BookDao {
        public void save();
    }
    @Repository
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
  • 创建运行类App

    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            BookDao bookDao1 = ctx.getBean(BookDao.class);
            BookDao bookDao2 = ctx.getBean(BookDao.class);
            System.out.println(bookDao1);
            System.out.println(bookDao2);
        }
    }

最终创建好的项目结构如下:

 3.4.2 Bean的作用范围

(1)先运行App类,在控制台打印两个一摸一样的地址,说明默认情况下bean是单例

(2)要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解

@Repository
//@Scope设置bean的作用范围
@Scope("prototype")
public class BookDaoImpl implements BookDao {
​
    public void save() {
        System.out.println("book dao save ...");
    }
}

再次执行App类,打印结果:

 知识点1:@Scope

名称@Scope
类型类注解
位置类定义上方
作用设置该类创建对象的作用范围 可用于设置创建出的bean是否为单例对象
属性value(默认):定义bean作用范围, ==默认值singleton(单例),可选值prototype(非单例)==

3.4.3 Bean的生命周期

(1)在BookDaoImpl中添加两个方法,initdestroy,方法名可以任意

@Repository
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    public void init() {
        System.out.println("init ...");
    }
    public void destroy() {
        System.out.println("destroy ...");
    }
}

(2)如何对方法进行标识,哪个是初始化方法,哪个是销毁方法?

只需要在对应的方法上添加@PostConstruct@PreDestroy注解即可。

@Repository
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    @PostConstruct //在构造方法之后执行,替换 init-method
    public void init() {
        System.out.println("init ...");
    }
    @PreDestroy //在销毁方法之前执行,替换 destroy-method
    public void destroy() {
        System.out.println("destroy ...");
    }
}

(3)要想看到两个方法执行,需要注意的是destroy只有在容器关闭的时候,才会执行,所以需要修改App的类

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao1 = ctx.getBean(BookDao.class);
        BookDao bookDao2 = ctx.getBean(BookDao.class);
        System.out.println(bookDao1);
        System.out.println(bookDao2);
        ctx.close(); //关闭容器
    }
}

(4)运行App,类查看打印结果,证明init和destroy方法都被执行了。

 ==注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包==

<dependency>
  <groupId>javax.annotation</groupId>
  <artifactId>javax.annotation-api</artifactId>
  <version>1.3.2</version>
</dependency>

找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。

知识点1:@PostConstruct

名称@PostConstruct
类型方法注解
位置方法上
作用设置该方法为初始化方法
属性

知识点2:@PreDestroy

名称@PreDestroy
类型方法注解
位置方法上
作用设置该方法为销毁方法
属性

小结

3.5 注解开发依赖注入

 Spring为了使用注解简化开发,并没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

3.5.1 环境准备

在学习之前,把案例环境介绍下:

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
  • 添加一个配置类SpringConfig

    @Configuration
    @ComponentScan("com.itheima")
    public class SpringConfig {
    }
  • 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类

    public interface BookDao {
        public void save();
    }
    @Repository
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
    public interface BookService {
        public void save();
    }
    @Service
    public class BookServiceImpl implements BookService {
        private BookDao bookDao;
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
  • 创建运行类App

    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            BookService bookService = ctx.getBean(BookService.class);
            bookService.save();
        }
    }

最终创建好的项目结构如下:

 环境准备好后,运行后会发现有问题

 出现问题的原因是,在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报控指针异常

3.5.2 注解实现按照类型注入

对于这个问题使用注解该如何解决?

(1) 在BookServiceImpl类的bookDao属性上添加@Autowired注解

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    
//    public void setBookDao(BookDao bookDao) {
//        this.bookDao = bookDao;
//    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

注意:

  • @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是写在属性上并将setter方法删除掉

  • 为什么setter方法可以删除呢?

    • 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值

    • 普通反射只能获取public修饰的内容

    • 暴力反射除了获取public修饰的内容还可以获取private修改的内容

    • 所以此处无需提供setter方法

(2)@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加BookDaoImpl2

@Repository
public class BookDaoImpl2 implements BookDao {
    public void save() {
        System.out.println("book dao save ...2");
    }
}

这个时候再次运行App,就会报错

 此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入

  • 先给两个Dao类分别起个名称

    @Repository("bookDao")
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
    @Repository("bookDao2")
    public class BookDaoImpl2 implements BookDao {
        public void save() {
            System.out.println("book dao save ...2" );
        }
    }

    此时就可以注入成功,但是得思考个问题:

    • @Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象,为什么不报错?

    • @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫bookDao而容器中也有一个booDao,所以可以成功注入。

    • 分析下面这种情况是否能完成注入呢?

    • 不行,因为按照类型会找到多个bean对象,此时会按照bookDao名称去找,因为IOC容器只有名称叫bookDao1bookDao2,所以找不到,会报NoUniqueBeanDefinitionException

3.5.3 注解实现按照名称注入

当根据类型在容器中找到多个bean,注入参数的属性名又和容器中bean的名称不一致,这个时候该如何解决,就需要使用到@Qualifier来指定注入哪个名称的bean对象。

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    @Qualifier("bookDao1")
    private BookDao bookDao;
    
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

@Qualifier注解后的值就是需要注入的bean的名称。

==注意:@Qualifier不能独立使用,必须和@Autowired一起使用==

3.5.4 简单数据类型注入

引用类型看完,简单类型注入就比较容易懂了。简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl类中添加一个name属性,用其进行简单类型注入

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

数据类型换了,对应的注解也要跟着换,这次使用@Value注解,将值写入注解的参数中就行了

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("itheima")
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

注意数据格式要匹配,如将"abc"注入给int值,这样程序就会报错。

介绍完后,会有一种感觉就是这个注解好像没什么用,跟直接赋值是一个效果,还没有直接赋值简单,所以这个注解存在的意义是什么?

3.5.5 注解读取properties配置文件

@Value一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?

步骤1:resource下准备properties文件

jdbc.properties

name=itheima888

步骤2: 使用注解加载properties配置文件

在配置类上添加@PropertySource注解

@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}

步骤3:使用@Value读取配置文件中的内容

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("${name}")
    private String name;
    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

步骤4:运行程序

运行App类,查看运行结果,说明配置文件中的内容已经被加载到

 注意:

  • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个

    @PropertySource({"jdbc.properties","xxx.properties"})
  • @PropertySource注解属性中不支持使用通配符*,运行会报错

    @PropertySource({"*.properties"})
  • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件

    @PropertySource({"classpath:jdbc.properties"})

知识点1:@Autowired

名称@Autowired
类型属性注解 或 方法注解(了解) 或 方法形参注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面
作用为引用类型属性设置值
属性required:true/false,定义该属性是否允许为null

知识点2:@Qualifier

名称@Qualifier
类型属性注解 或 方法注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方
作用为引用类型属性指定注入的beanId
属性value(默认):设置注入的beanId

知识点3:@Value

名称@Value
类型属性注解 或 方法注解(了解)
位置属性定义上方 或 标准set方法上方 或 类set方法上方
作用为 基本数据类型 或 字符串类型 属性设置值
属性value(默认):要注入的属性值

知识点4:@PropertySource

名称@PropertySource
类型类注解
位置类定义上方
作用加载properties文件中的属性值
属性value(默认):设置加载的properties文件对应的文件名或文件名组成的数组

4、IOC/DI注解开发管理第三方bean

前面定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解,这个时候该怎么办?

遇到上述问题,我们就需要有一种更加灵活的方式来定义bean,这种方式不能在原始代码上面书写注解,一样能定义bean,这就用到了一个全新的注解==@Bean==。

这个注解该如何使用呢?

咱们把之前使用配置方式管理的数据源使用注解再来一遍,通过这个案例来学习下@Bean的使用

 4.1 环境准备

学习@Bean注解之前先来准备环境:

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
  • 添加一个配置类SpringConfig

    @Configuration
    public class SpringConfig {
    }
  • 添加BookDao、BookDaoImpl类

    public interface BookDao {
        public void save();
    }
    @Repository
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
  • 创建运行类App

    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        }
    }

最终创建好的项目结构如下:

 

4.2 注解开发管理第三方bean

在上述环境中完成对Druid数据源的管理,具体的实现步骤为:

步骤1:导入对应的jar包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

步骤2:在配置类中添加一个方法

注意该方法的返回值就是要创建的Bean对象类型

@Configuration
public class SpringConfig {
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

步骤3:在方法上添加@Bean注解

@Bean注解的作用是将方法的返回值制作为Spring管理的一个bean对象

@Configuration
public class SpringConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

注意:不能使用DataSource ds = new DruidDataSource()

因为DataSource接口中没有对应的setter方法来设置属性。

步骤4:从IOC容器中获取对象并打印

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

至此使用@Bean来管理第三方bean的案例就已经完成。

如果有多个bean要被Spring管理,直接在配置类中多些几个方法,方法上添加@Bean注解即可。

4.3 引入外部配置类

 如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?

对于数据源的bean,我们新建一个JdbcConfig配置类,并把数据源配置到该类下。

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

现在的问题是,这个配置类如何能被Spring配置类加载到,并创建DataSource对象在IOC容器中?

针对这个问题,有两个解决方案:

4.3.1 使用包扫描引入

步骤1:在Spring的配置类上添加包扫描

@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {
    
}

步骤2:在JdbcConfig上添加配置注解

JdbcConfig类要放入到com.itheima.config包下,需要被Spring的配置类扫描到即可

@Configuration
public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

步骤3:运行程序

依然能获取到bean对象并打印控制台。

这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。

4.3.2 使用@Import引入

方案一实现起来有点小复杂,Spring早就想到了这一点,于是又给我们提供了第二种方案。

这种方案可以不用加@Configuration注解,但是必须在Spring配置类上使用@Import注解手动引入需要加载的配置类

步骤1:去除JdbcConfig类上的注解

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

步骤2:在Spring配置类中引入

@Configuration
//@ComponentScan("com.itheima.config")
@Import({JdbcConfig.class})
public class SpringConfig {
    
}

注意:

  • 扫描注解可以移除

  • @Import参数需要的是一个数组,可以引入多个配置类。

  • @Import注解在配置类中只能写一次,下面的方式是==不允许的==

    @Configuration
    //@ComponentScan("com.itheima.config")
    @Import(JdbcConfig.class)
    @Import(Xxx.class)
    public class SpringConfig {
        
    }

步骤3:运行程序

依然能获取到bean对象并打印控制台

知识点1:@Bean

名称@Bean
类型方法注解
位置方法定义上方
作用设置该方法的返回值作为spring管理的bean
属性value(默认):定义bean的id

知识点2:@Import

名称@Import
类型类注解
位置类定义上方
作用导入配置类
属性value(默认):定义导入的配置类类名, 当配置类有多个时使用数组格式一次性导入多个配置类

 4.4 注解开发实现为第三方bean注入资源

 在使用@Bean创建bean对象的时候,如果方法在创建的过程中需要其他资源该怎么办?

这些资源会有两大类,分别是简单数据类型引用数据类型

4.4.1 简单数据类型

4.4.1.1 需求分析

对于下面代码关于数据库的四要素不应该写死在代码中,应该是从properties配置文件中读取。如何来优化下面的代码?

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

4.4.1.2 注入简单数据类型步骤

步骤1:类中提供四个属性

public class JdbcConfig {
    private String driver;
    private String url;
    private String userName;
    private String password;
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

步骤2:使用@Value注解引入值

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("password")
    private String password;
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

扩展

现在的数据库连接四要素还是写在代码中,需要做的是将这些内容提

取到jdbc.properties配置文件,大家思考下该如何实现?

1.resources目录下添加jdbc.properties

2.配置文件中提供四个键值对分别是数据库的四要素

3.使用@PropertySource加载jdbc.properties配置文件

4.修改@Value注解属性的值,将其修改为${key},key就是键值对中的键的值

具体的实现就交由大家自行实现下。

4.4.2 引用数据类型

4.4.2.1 需求分析

假设在构建DataSource对象的时候,需要用到BookDao对象,该如何把BookDao对象注入进方法内让其使用呢?

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

4.4.2.2 注入引用数据类型步骤

步骤1:在SpringConfig中扫描BookDao

扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象

@Configuration
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}

步骤2:在JdbcConfig类的方法上添加参数

@Bean
public DataSource dataSource(BookDao bookDao){
    System.out.println(bookDao);
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driver);
    ds.setUrl(url);
    ds.setUsername(userName);
    ds.setPassword(password);
    return ds;
}

==引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。==

步骤3:运行程序

5、注解开发总结

前面我们已经完成了XML配置和注解的开发实现,至于两者之间的差异,咱们放在一块去对比回顾下:

6、Spring整合

课程学习到这里,已经对Spring有一个简单的认识了,Spring有一个容器,叫做IoC容器,里面保存bean。在进行企业级开发的时候,其实除了将自己写的类让Spring管理之外,还有一部分重要的工作就是使用第三方的技术。前面已经讲了如何管理第三方bean了,下面结合IoC和DI,整合2个常用技术,进一步加深对Spring的使用理解。 

6.1 Spring整合Mybatis思路分析

6.1.1 环境准备

在准备环境的过程中,我们也来回顾下Mybatis开发的相关内容:

步骤1:准备数据库表

Mybatis是来操作数据库表,所以先创建一个数据库及表

create database spring_db character set utf8;
use spring_db;
create table tbl_account(
    id int primary key auto_increment,
    name varchar(35),
    money double
);

步骤2:创建项目导入jar包

项目的pom.xml添加相关依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
</dependencies>

步骤3:根据表创建模型类

public class Account implements Serializable {
​
    private Integer id;
    private String name;
    private Double money;
    //setter...getter...toString...方法略    
}

步骤4:创建Dao接口

public interface AccountDao {
​
    @Insert("insert into tbl_account(name,money)values(#{name},#{money})")
    void save(Account account);
​
    @Delete("delete from tbl_account where id = #{id} ")
    void delete(Integer id);
​
    @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
    void update(Account account);
​
    @Select("select * from tbl_account")
    List<Account> findAll();
​
    @Select("select * from tbl_account where id = #{id} ")
    Account findById(Integer id);
}

步骤5:创建Service接口和实现类

public interface AccountService {
​
    void save(Account account);
​
    void delete(Integer id);
​
    void update(Account account);
​
    List<Account> findAll();
​
    Account findById(Integer id);
​
}
​
@Service
public class AccountServiceImpl implements AccountService {
​
    @Autowired
    private AccountDao accountDao;
​
    public void save(Account account) {
        accountDao.save(account);
    }
​
    public void update(Account account){
        accountDao.update(account);
    }
​
    public void delete(Integer id) {
        accountDao.delete(id);
    }
​
    public Account findById(Integer id) {
        return accountDao.findById(id);
    }
​
    public List<Account> findAll() {
        return accountDao.findAll();
    }
}

步骤6:添加jdbc.properties文件

resources目录下添加,用于配置数据库连接四要素

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root

useSSL:关闭MySQL的SSL连接

步骤7:添加Mybatis核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--读取外部properties配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!--别名扫描的包路径-->
    <typeAliases>
        <package name="com.itheima.domain"/>
    </typeAliases>
    <!--数据源-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件扫描包路径-->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

步骤8:编写应用程序

public class App {
    public static void main(String[] args) throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 2. 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak");
        // 3. 创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        // 4. 获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 5. 执行SqlSession对象执行查询,获取结果User
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
​
        Account ac = accountDao.findById(1);
        System.out.println(ac);
​
        // 6. 释放资源
        sqlSession.close();
    }
}

步骤9:运行程序

 6.1.2 整合思路分析

Mybatis的基础环境我们已经准备好了,接下来就得分析下在上述的内容中,哪些对象可以交给Spring来管理?

  • Mybatis程序核心对象分析

  • 从图中可以获取到,真正需要交给Spring管理的是==SqlSessionFactory==

  • 整合Mybatis,就是将Mybatis用到的内容交给Spring管理,分析下配置文件

  • 说明:

    • 第一行读取外部properties配置文件,Spring有提供具体的解决方案@PropertySource,需要交给Spring

    • 第二行起别名包扫描,为SqlSessionFactory服务的,需要交给Spring

    • 第三行主要用于做连接池,Spring之前我们已经整合了Druid连接池,这块也需要交给Spring

    • 前面三行一起都是为了创建SqlSession对象用的,那么用Spring管理SqlSession对象吗?回忆下SqlSession是由SqlSessionFactory创建出来的,所以只需要将SqlSessionFactory交给Spring管理即可。

    • 第四行是Mapper接口和映射文件[如果使用注解就没有该映射文件],这个是在获取到SqlSession以后执行具体操作的时候用,所以它和SqlSessionFactory创建的时机都不在同一个时间,可能需要单独管理。

6.2 Spring整合Mybatis

前面我们已经分析了Spring与Mybatis的整合,大体需要做两件事,

第一件事是:Spring要管理MyBatis中的SqlSessionFactory

第二件事是:Spring要管理Mapper接口的扫描

具体该如何实现,具体的步骤为:

步骤1:项目中导入整合需要的jar包

<dependency>
    <!--Spring操作数据库需要该jar包-->
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
    <!--
        Spring与Mybatis整合的jar包
        这个jar包mybatis在前面,是Mybatis提供的
    -->
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
</dependency>

步骤2:创建Spring的主配置类

//配置类注解
@Configuration
//包扫描,主要扫描的是项目中的AccountServiceImpl类
@ComponentScan("com.itheima")
public class SpringConfig {
}

​步骤3:创建数据源的配置类

在配置类中完成数据源的创建

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;
​
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

步骤4:主配置类中读properties并引入数据源配置类

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import(JdbcConfig.class)
public class SpringConfig {
}

​步骤5:创建Mybatis配置类并配置SqlSessionFactory

public class MybatisConfig {
    //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        //设置模型类的别名扫描
        ssfb.setTypeAliasesPackage("com.itheima.domain");
        //设置数据源
        ssfb.setDataSource(dataSource);
        return ssfb;
    }
    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}

说明:

  • 使用SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息

    • SqlSessionFactoryBean是前面我们讲解FactoryBean的一个子类,在该类中将SqlSessionFactory的创建进行了封装,简化对象的创建,我们只需要将其需要的内容设置即可。

    • 方法中有一个参数为dataSource,当前Spring容器中已经创建了Druid数据源,类型刚好是DataSource类型,此时在初始化SqlSessionFactoryBean这个对象的时候,发现需要使用DataSource对象,而容器中刚好有这么一个对象,就自动加载了DruidDataSource对象。

  • 使用MapperScannerConfigurer加载Dao接口,创建代理对象保存到IOC容器中

    • 这个MapperScannerConfigurer对象也是MyBatis提供的专用于整合的jar包中的类,用来处理原始配置文件中的mappers相关配置,加载数据层的Mapper接口类

    • MapperScannerConfigurer有一个核心属性basePackage,就是用来设置所扫描的包路径

步骤6:主配置类中引入Mybatis配置类

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}

步骤7:编写运行类

在运行类中,从IOC容器中获取Service对象,调用方法获取结果

public class App2 {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
​
        AccountService accountService = ctx.getBean(AccountService.class);
​
        Account ac = accountService.findById(1);
        System.out.println(ac);
    }
}

步骤8:运行程序

 支持Spring与Mybatis的整合就已经完成了,其中主要用到的两个类分别是:

  • ==SqlSessionFactoryBean==

  • ==MapperScannerConfigurer==

6.3 Spring整合Junit

整合Junit与整合Druid和MyBatis差异比较大,为什么呢?Junit是一个搞单元测试用的工具,它不是我们程序的主体,也不会参加最终程序的运行,从作用上来说就和之前的东西不一样,它不是做功能的,看做是一个辅助工具就可以了。

6.3.1 环境准备

这块环境,大家可以直接使用Spring与Mybatis整合的环境即可。当然也可以重新创建一个,因为内容是一模一样,所以我们直接来看下项目结构即可:

6.3.2 整合Junit步骤

在上述环境的基础上,我们来对Junit进行整合。

步骤1:引入依赖

pom.xml

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
​
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>

步骤2:编写测试类

在test\java下创建一个AccountServiceTest,这个名字任意

//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = {SpringConfiguration.class}) //加载配置类
//@ContextConfiguration(locations={"classpath:applicationContext.xml"})//加载配置文件
public class AccountServiceTest {
    //支持自动装配注入bean
    @Autowired
    private AccountService accountService;
    @Test
    public void testFindById(){
        System.out.println(accountService.findById(1));
​
    }
    @Test
    public void testFindAll(){
        System.out.println(accountService.findAll());
    }
}

注意:

  • 单元测试,如果测试的是注解配置类,则使用@ContextConfiguration(classes = 配置类.class)

  • 单元测试,如果测试的是配置文件,则使用@ContextConfiguration(locations={配置文件名,...})

  • Junit运行后是基于Spring环境运行的,所以Spring提供了一个专用的类运行器,这个务必要设置,这个类运行器就在Spring的测试专用包中提供的,导入的坐标就是这个东西SpringJUnit4ClassRunner

  • 上面两个配置都是固定格式,当需要测试哪个bean时,使用自动装配加载对应的对象,下面的工作就和以前做Junit单元测试完全一样了

知识点1:@RunWith

名称@RunWith
类型测试类注解
位置测试类定义上方
作用设置JUnit运行器
属性value(默认):运行所使用的运行期

知识点2:@ContextConfiguration

名称@ContextConfiguration
类型测试类注解
位置测试类定义上方
作用设置JUnit加载的Spring核心配置
属性classes:核心配置类,可以使用数组的格式设定加载多个配置类 locations:配置文件,可以使用数组的格式设定加载多个配置文件名称

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
因为上传大小的限制,分为两部分上传,这是第二部分,第一部分会在评论中给出链接 绝对是spring攻略中文版第二版 Spring专家力作 理论与实践完美结合 问题描述→解决方案→实现方法 第一部分 核心概念  第1章 控制反转和容器    1.1 使用容器管理组件     1.1.1 问题描述     1.1.2 解决方案     1.1.3 实现方法    1.2 使用服务定位器降低查找组件的复杂性     1.2.1 问题描述     1.2.2 解决方案     1.2.3 实现方法    1.3 应用控制反转和依赖注入     1.3.1 问题描述     1.3.2 解决方案     1.3.3 实现方法    1.4 理解不同类型的依赖注入     1.4.1 问题描述     1.4.2 解决方案     1.4.3 实现方法    1.5 使用配置文件配置容器      1.5.1 问题描述     1.5.2 解决方案     1.5.3 实现方法    1.6 小结   第2章 Spring简介    2.1 Spring Framework     2.1.1 Spring的模块介绍     2.1.2 Spring的发布版本     2.1.3 Spring的项目    2.2 安装Spring Framework     2.2.1 问题描述     2.2.2 解决方案     2.2.3 实现方法    2.3 建立Spring项目     2.3.1 问题描述     2.3.2 解决方案     2.3.3 实现方法    2.4 安装Spring IDE     2.4.1 问题描述     2.4.2 解决方案     2.4.3 实现方法    2.5 使用Spring IDE的Bean-supporting特性     2.5.1 问题描述     2.5.2 解决方案     2.5.3 实现方法    2.6 小结   第3章 Spring中的Bean配置    3.1 在Spring IoC容器里配置Bean     3.1.1 问题描述     3.1.2 解决方案     3.1.3 实现方法   3.2 实例化Spring IoC容器      3.2.1 问题描述     3.2.2 解决方案     3.2.3 实现方法    3.3 解决构造器歧义     3.3.1 问题描述     3.3.2 解决方案     3.3.3 实现方法   第4章 高级Spring IoC容器   第5章 动态代理和经典的Spring AOP   第6章 Spring 2.x AOP和AspectJ支持  第二部分 基础主题  第7章 Spring对JDBC的支持   第8章 Spring中的事务管理   第9章 Spring对ORM的支持   第10章 Spring MVC框架   第11章 整合Spring与其他Web框架   第12章 Spring对测试的支持  第三部分 高级主题  第13章 Spring Security框架   第14章 Spring Portlet MVC框架   第15章 Spring Web Flow   第16章 Spring远程服务和Web服务   第17章 Spring对EJB和JMS的支持   第18章 Spring对JMX、电子邮件和调度的支持   第19章 Spring中的脚本编程 
本书共分为两卷。 第1章 Spring简介 1 1.1 实例化Spring IoC容器 1 1.1.1 问题 1 1.1.2 解决方案 1 1.1.3 工作原理 3 1.2 配置Spring IoC容器中的Bean 4 1.2.1 问题 4 1.2.2 解决方案 4 1.2.3 工作原理 4 1.3 调用构造程序创建Bean 14 1.3.1 问题 14 1.3.2 解决方案 14 1.3.3 工作原理 14 1.4 解决构造程序歧义 17 1.4.1 问题 17 1.4.2 解决方案 17 1.4.3 工作原理 17 1.5 指定Bean引用 20 1.5.1 问题 20 1.5.2 解决方案 20 1.5.3 工作原理 20 1.6 为集合元素指定数据类型 24 1.6.1 问题 24 1.6.2 解决方案 24 1.6.3 工作原理 24 1.7 使用Spring的FactoryBean创建Bean 27 1.7.1 问题 27 1.7.2 解决方案 27 1.7.3 工作原理 27 1.8 使用工厂Bean和Utility Schema定义集合 29 1.8.1 问题 29 1.8.2 解决方案 29 1.8.3 工作原理 29 1.9 用依赖检查属性 31 1.9.1 问题 31 1.9.2 解决方案 32 1.9.3 工作原理 32 1.10 用@Required注解检查属性 34 1.10.1 问题 34 1.10.2 解决方案 34 1.10.3 工作原理 34 1.11 用XML配置自动装配Bean 36 1.11.1 问题 36 1.11.2 解决方案 36 1.11.3 工作原理 37 1.12 用@Autowired和@Resource自动装配Bean 41 1.12.1 问题 41 1.12.2 解决方案 41 1.12.3 工作原理 41 1.13 继承Bean配置 47 1.13.1 问题 47 1.13.2 解决方案 47 1.13.3 工作原理 48 1.14 从Classpath中扫描组件 50 1.14.1 问题 50 1.14.2 解决方案 51 1.14.3 工作原理 51 1.15 小结 56 第2章 高级Spring IoC容器 57 2.1 调用静态工厂方法创建Bean 57 2.1.1 问题 57 2.1.2 解决方案 57 2.1.3 工作原理 57 2.2 调用一个实例工厂方法创建Bean 58 2.2.1 问题 58 2.2.2 解决方案 59 2.2.3 工作原理 59 2.3 从静态字段中声明Bean 60 2.3.1 问题 60 2.3.2 解决方案 60 2.3.3 工作原理 61 2.4 从对象属性中声明Bean 62 2.4.1 问题 62 2.4.2 解决方案 62 2.4.3 工作原理 62 2.5 使用Spring表达式语言 64 2.5.1 问题 64 2.5.2 解决方案 64 2.5.3 工作原理 65 2.6 设置Bean作用域 69 2.6.1 问题 69 2.6.2 解决方案 69 2.6.3 工作原理 70 2.7 自定义Bean初始化和析构 72 2.7.1 问题 72 2.7.2 解决方案 72 2.7.3 工作原理 72 2.8 用Java Config简化XML配置 77 2.8.1 问题 77 2.8.2 解决方案 77 2.8.3 工作原理 77 2.9 使Bean感知容器 81 2.9.1 问题 81 2.9.2 解决方案 81 2.9.3 工作原理 82 2.10 加载外部资源 82 2.10.1 问题 82 2.10.2 解决方案 83 2.10.3 工作原理 83 2.11 创建Bean后处理器 85 2.11.1 问题 85 2.11.2 解决方案 85 2.11.3 工作原理 86 2.12 外部化Bean配置 89 2.12.1 问题 89 2.12.2 解决方案 89 2.12.3 工作原理 90 2.13 解析文本消息 91 2.13.1 问题 91 2.13.2 解决方案 91 2.13.3 工作原理 91 2.14 使用应用事件进行通信 93 2.14.1 问题 93 2.14.2 解决方案 93 2.14.3 工作原理 94 2.15 在Spring中注册属性编辑器 96 2.15.1 问题 96 2.15.2 解决方案 96 2.15.3 工作原理 97 2.16 创建自定义属性编辑器 99 2.16.1 问题 99 2.16.2 解决方案 100 2.16.3 工作原理 100 2.17 使用TaskExecutor实现并发性 101 2.17.1 问题 101 2.17.2 解决方案 101 2.17.3 工作原理 102 2.18 小结 110 第3章 Spring AOP和AspectJ支持 112 3.1 启用Spring的AspectJ注解支持 113 3.1.1 问题 113 3.1.2 解决方案 113 3.1.3 工作原理 113 3.2 用AspectJ注解声明aspect 115 3.2.1 问题 115 3.2.2 解决方案 115 3.2.3 工作原理 116 3.3 访问连接点信息 121 3.3.1 问题 121 3.3.2 解决方案 122 3.3.3 工作原理 122 3.4 指定aspect优先级 123 3.4.1 问题 123 3.4.2 解决方案 123 3.4.3 工作原理 123 3.5 重用切入点定义 125 3.5.1 问题 125 3.5.2 解决方案 125 3.5.3 工作原理 125 3.6 编写AspectJ切入点表达式 127 3.6.1 问题 127 3.6.2 解决方案 127 3.6.3 工作原理 128 3.7 在你的Bean中引入行为 132 3.7.1 问题 132 3.7.2 解决方案 132 3.7.3 工作原理 132 3.8 为你的Bean引入状态 135 3.8.1 问题 135 3.8.2 解决方案 135 3.8.3 工作原理 135 3.9 用基于XML的配置声明aspect 137 3.9.1 问题 137 3.9.2 解决方案 137 3.9.3 工作原理 137 3.10 Spring中的AspectJ加载时织入aspect 140 3.10.1 问题 140 3.10.2 解决方案 141 3.10.3 工作原理 141 3.11 在Spring中配置AspectJ aspect 146 3.11.1 问题 146 3.11.2 解决方案 146 3.11.3 工作原理 146 3.12 将Spring Bean注入领域对象 147 3.12.1 问题 147 3.12.2 解决方案 147 3.12.3 工作原理 148 3.13 小结 151 第4章 Spring中的脚本 152 4.1 用脚本语言实现Bean 152 4.1.1 问题 152 4.1.2 解决方案 153 4.1.3 工作原理 153 4.2 将Spring Bean注入脚本中 157 4.2.1 问题 157 4.2.2 解决方案 157 4.2.3 工作原理 157 4.3 从脚本中刷新Bean 160 4.3.1 问题 160 4.3.2 解决方案 160 4.3.3 工作原理 160 4.4 定义内联脚本源码 161 4.4.1 问题 161 4.4.2 解决方案 161 4.4.3 工作原理 161 4.5 小结 163 第5章 Spring Security 164 5.1 加强URL访问安全 165 5.1.1 问题 165 5.1.2 解决方案 165 5.1.3 工作原理 166 5.2 登录到Web应用 175 5.2.1 问题 175 5.2.2 解决方案 175 5.2.3 工作原理 175 5.3 验证用户 179 5.3.1 问题 179 5.3.2 解决方案 180 5.3.3 工作原理 180 5.4 做出访问控制决策 190 5.4.1 问题 190 5.4.2 解决方案 190 5.4.3 工作原理 191 5.5 加强方法调用的安全 193 5.5.1 问题 193 5.5.2 解决方案 193 5.5.3 工作原理 194 5.6 处理视图中的安全性 196 5.6.1 问题 196 5.6.2 解决方案 196 5.6.3 工作原理 196 5.7 处理领域对象安全性 198 5.7.1 问题 198 5.7.2 解决方案 198 5.7.3 工作原理 199 5.8 小结 208 第6章 将Spring与其他Web框架集成 209 6.1 在一般Web应用中访问Spring 209 6.1.1 问题 209 6.1.2 解决方案 210 6.1.3 工作原理 210 6.2 在你的Servlet和过滤器中使用Spring 214 6.2.1 问题 214 6.2.2 解决方案 215 6.2.3 工作原理 215 6.3 将Spring与Struts 1.x集成 220 6.3.1 问题 220 6.3.2 解决方案 220 6.3.3 工作原理 220 6.4 将Spring与JSF集成 226 6.4.1 问题 226 6.4.2 解决方案 226 6.4.3 工作原理 227 6.5 将Spring与DWR集成 232 6.5.1 问题 232 6.5.2 解决方案 232 6.5.3 工作原理 233 6.6 小结 236 第7章 Spring Web Flow 238 7.1 用Spring Web Flow管理简单的UI流程 238 7.1.1 问题 238 7.1.2 解决方案 239 7.1.3 工作原理 239 7.2 用不同状态类型建立Web流程模型 246 7.2.1 问题 246 7.2.2 解决方案 246 7.2.3 工作原理 246 7.3 加强Web流程安全 257 7.3.1 问题 257 7.3.2 解决方案 258 7.3.3 工作原理 258 7.4 持续存储Web流程中的对象 260 7.4.1 问题 260 7.4.2 解决方案 260 7.4.3 工作原理 260 7.5 将Spring Web Flow与JSF集成 267 7.5.1 问题 267 7.5.2 解决方案 267 7.5.3 工作原理 267 7.6 使用RichFaces与Spring WebFlow协作 275 7.6.1 问题 275 7.6.2 解决方案 275 7.6.3 方法 275 7.7 小结 279 第8章 Spring @MVC 280 8.1 用Spring MVC开发简单的Web应用 280 8.1.1 问题 280 8.1.2 解决方案 281 8.1.3 工作原理 283 8.2 用@RequestMapping映射请求 293 8.2.1 问题 293 8.2.2 解决方案 294 8.2.3 工作原理 294 8.3 用处理程序拦截器拦截请求 297 8.3.1 问题 297 8.3.2 解决方案 298 8.3.3 工作原理 298 8.4 解析用户区域 302 8.4.1 问题 302 8.4.2 解决方案 302 8.4.3 工作原理 302 8.5 外部化区分区域的文本信息 304 8.5.1 问题 304 8.5.2 解决方案 304 8.5.3 工作原理 305 8.6 按照名称解析视图 306 8.6.1 问题 306 8.6.2 解决方案 306 8.6.3 工作原理 306 8.7 视图和内容协商 309 8.7.1 问题 309 8.7.2 解决方案 309 8.7.3 工作原理 309 8.8 映射异常视图 312 8.8.1 问题 312 8.8.2 解决方案 312 8.8.3 工作原理 312 8.9 用@Value在控制器中赋值 314 8.9.1 问题 314 8.9.2 解决方案 314 8.9.3 工作原理 314 8.10 用控制器处理表单 316 8.10.1 问题 316 8.10.2 解决方案 316 8.10.3 工作原理 317 8.11 用向导表单控制器处理多页表单 331 8.11.1 问题 331 8.11.2 解决方案 331 8.11.3 工作原理 332 8.12 使用注解(JSR-303)的Bean校验 341 8.12.1 问题 341 8.12.2 解决方案 342 8.12.3 工作原理 342 8.13 创建Excel和PDF视图 344 8.13.1 问题 344 8.13.2 解决方案 345 8.13.3 工作原理 345 8.14 小结 351 第9章 Spring REST 352 9.1 用Spring发布一个REST服务 352 9.1.1 问题 352 9.1.2 解决方案 353 9.1.3 工作原理 353 9.2 用Spring访问REST服务 358 9.2.1 问题 358 9.2.2 解决方案 358 9.2.3 工作原理 358 9.3 发布RSS和Atom信息源 362 9.3.1 问题 362 9.3.2 解决方案 363 9.3.3 工作原理 363 9.4 用REST服务发布JSON 372 9.4.1 问题 372 9.4.2 解决方案 372 9.4.3 工作原理 372 9.5 访问具有复杂XML响应的REST服务 375 9.5.1 问题 375 9.5.2 解决方案 375 9.5.3 工作原理 375 9.6 小结 385 第10章 Spring和Flex 386 10.1 Flex入门 388 10.1.1 问题 388 10.1.2 解决方案 388 10.1.3 工作原理 388 10.2 离开沙箱 393 10.2.1 问题 393 10.2.2 解决方案 394 10.2.3 工作原理 394 10.3 为应用添加Spring BlazeDS支持 406 10.3.1 问题 406 10.3.2 解决方案 406 10.3.3 工作原理 406 10.4 通过BlazeDS/Spring暴露服务 411 10.4.1 问题 411 10.4.2 解决方案 411 10.4.3 工作原理 411 10.5 使用服务器端对象 418 10.5.1 问题 418 10.5.2 解决方案 418 10.5.3 工作原理 418 10.6 使用BlazeDS和Spring消费面向消息的服务 421 10.6.1 问题 421 10.6.2 解决方案 422 10.6.3 工作原理 422 10.7 将依赖注入带给你的ActionScript客户 434 10.7.1 问题 434 10.7.2 解决方案 434 10.7.3 工作原理 435 10.8 小结 439 第11章 Grails 441 11.1 获取和安装Grails 441 11.1.1 问题 441 11.1.2 解决方案 442 11.1.3 工作原理 442 11.2 创建Grails应用 443 11.2.1 问题 443 11.2.2 解决方案 443 11.2.3 工作原理 443 11.3 Grails插件 447 11.3.1 问题 447 11.3.2 解决方案 448 11.3.3 工作原理 448 11.4 在Grails环境中开发、生产和测试 449 11.4.1 问题 449 11.4.2 解决方案 449 11.4.3 工作原理 450 11.5 创建应用的领域类 452 11.5.1 问题 452 11.5.2 解决方案 452 11.5.3 工作原理 452 11.6 为一个应用的领域类生成CRUD控制器和视图 454 11.6.1 问题 454 11.6.2 解决方案 454 11.6.3 工作原理 455 11.7 国际化(I18n)信息属性 458 11.7.1 问题 458 11.7.2 解决方案 458 11.7.3 工作原理 458 11.8 改变永久性存储系统 461 11.8.1 问题 461 11.8.2 解决方案 461 11.4.3 工作原理 461 11.9 日志 464 11.9.1 问题 464 11.9.2 解决方案 464 11.9.3 工作原理 464 11.10 运行单元和集成测试 466 11.10.1 问题 466 11.10.2 解决方案 467 11.10.3 工作原理 467 11.11 使用自定义布局和模板 472 11.11.1 问题 472 11.11.2 解决方案 472 11.11.3 工作原理 472 11.12 使用GORM查询 475 11.12.1 问题 475 11.12.2 解决方案 475 11.12.3 工作原理 475 11.13 创建自定义标记 477 11.13.1 问题 477 11.13.2 解决方案 477 11.13.3 工作原理 478 11.14 小结 479 第12章 Spring Roo 481 12.1 设置Spring Roo开发环境 483 12.1.1 问题 483 12.1.2 解决方案 483 12.1.3 工作原理 483 12.2 创建第一个Spring Roo项目 486 12.2.1 问题 486 12.2.2 解决方案 486 12.2.3 工作原理 486 12.3 把现有项目导入SpringSource Tool Suite 491 12.3.1 问题 491 12.3.2 解决方案 492 12.3.3 工作原理 492 12.4 更快地构建更好的应用程序 493 12.4.1 问题 493 12.4.2 解决方案 494 12.4.3 工作原理 494 12.5 从项目中删除Spring Roo 500 12.5.1 问题 500 12.5.2 解决方案 500 12.5.3 工作原理 501 12.6 小结 502 第13章 Spring测试 503 13.1 用JUnit and TestNG创建测试 504 13.1.1 问题 504 13.1.2 解决方案 504 13.1.3 工作原理 504 13.2 创建单元测试和集成测试 509 13.2.1 问题 509 13.2.2 解决方案 509 13.2.3 工作原理 510 13.3 Spring MVC控制器的单元测试 518 13.3.1 问题 518 13.3.2 解决方案 518 13.3.3 工作原理 518 13.4 管理集成测试中的应用上下文 520 13.4.1 问题 520 13.4.2 解决方案 520 13.4.3 工作原理 521 13.5 向集成测试注入测试夹具 526 13.5.1 问题 526 13.5.2 解决方案 526 13.5.3 工作原理 527 13.6 管理集成测试中的事务 530 13.6.1 问题 530 13.6.2 解决方案 530 13.6.3 工作原理 531 13.7 在集成测试中访问数据库 536 13.7.1 问题 536 13.7.2 解决方案 536 13.7.3 工作原理 537 13.8 使用Spring的常用测试注解 540 13.8.1 问题 540 13.8.2 解决方案 540 13.8.3 工作原理 541 13.9 小结 542 第14章 Spring Portlet MVC框架 544 14.1 用Spring Portlet MVC开发一个简单的Portlet 544 14.1.1 问题 544 14.1.2 解决方案 545 14.1.3 工作原理 546 14.2 将Portlet请求映射到处理程序 553 14.2.1 问题 553 14.2.2 解决方案 553 14.2.3 工作原理 554 14.3 用简单的表单控制器处理portlet表单 561 14.3.1 问题 561 14.3.2 解决方案 561 14.3.3 工作原理 561 14.4 小结 569 第15章 数据访问 570 15.1 Direct JDBC的问题 571 15.1.1 建立应用数据库 571 15.1.2 理解数据访问对象设计模式 573 15.1.3 用JDBC实现DAO 573 15.1.4 在Spring中配置数据源 575 15.1.5 运行DAO 577 15.1.6 更进一步 577 15.2 使用JDBC模板更新数据库 578 15.2.1 问题 578 15.2.2 解决方案 578 15.2.3 工作原理 578 15.3 使用JDBC模板查询数据库 583 15.3.1 问题 583 15.3.2 解决方案 583 15.3.3 工作原理 583 15.4 简化JDBC模板创建 588 15.4.1 问题 588 15.4.2 解决方案 588 15.4.3 工作原理 589 15.5 在Java 1.5中使用简单的JDBC模板 591 15.5.1 问题 591 15.5.2 解决方案 591 15.5.3 工作原理 591 15.6 在JDBC模板中使用命名参数 595 15.6.1 问题 595 15.6.2 解决方案 595 15.6.3 工作原理 595 15.7 在Spring JDBC框架中处理异常 597 15.7.1 问题 597 15.7.2 解决方案 597 15.7.3 工作原理 598 15.8 直接使用ORM框架的问题 602 15.8.1 问题 602 15.8.2 解决方案 603 15.8.3 工作原理 603 15.8.4 使用Hibernate API,用Hibernate XML映射持续化对象 604 15.8.5 使用Hibernate API,以JPA注解持续化对象 608 15.8.6 使用JPA,以Hibernate为引擎持续化对象 610 15.9 在Spring中配置ORM资源工厂 613 15.9.1 问题 613 15.9.2 解决方案 614 15.9.3 工作原理 614 15.10 用Spring ORM模板持续化对象 620 15.10.1 问题 620 15.10.2 解决方案 620 15.10.3 工作原理 621 15.11 用Hibernate的上下文会话持续化对象 626 15.11.1 问题 626 15.11.2 解决方案 626 15.11.3 工作原理 626 15.12 用JPA的上下文注入持续化对象 629 15.12.1 问题 629 15.12.2 解决方案 629 15.12.3 工作原理 630 15.13 小结 632 第16章 Spring中的事务管理 634 16.1 事务管理的问题 635 16.2 选择一个事务管理器实现 641 16.2.1 问题 641 16.2.2 解决方案 641 16.2.3 工作原理 641 16.3 用事务管理器API编程管理事务 642 16.3.1 问题 642 16.3.2 解决方案 643 16.3.3 工作原理 643 16.4 用事务模板编程管理事务 644 16.4.1 问题 644 16.4.2 解决方案 645 16.4.3 工作原理 645 16.5 用事务通知声明式地管理事务 647 16.5.1 问题 647 16.5.2 解决方案 648 16.5.3 工作原理 648 16.6 用@Transactional注解声明式地管理事务 650 16.6.1 方法 650 16.6.2 解决方案 650 16.6.3 工作原理 650 16.7 设置事务传播属性 652 16.7.1 问题 652 16.7.2 解决方案 652 16.7.3 工作原理 653 16.8 设置隔离事务属性 657 16.8.1 问题 657 16.8.2 解决方案 657 16.8.3 工作原理 658 16.9 设置Rollback事务属性 664 16.9.1 问题 664 16.9.2 解决方案 664 16.9.3 工作原理 664 16.10 设置超时和只读事务属性 666 16.10.1 问题 666 16.10.2 解决方案 666 16.10.3 工作原理 666 16.11 用加载时织入管理事务 667 16.11.1 问题 667 16.11.2 解决方案 667 16.11.3 工作原理 667 16.12 小结 671 第17章 EJB、Spring Remoting和Web服务 672 17.1 通过RMI暴露和调用服务 672 17.1.1 问题 672 17.1.2 解决方案 673 17.1.3 工作原理 673 17.2 用Spring创建EJB 2.x组件 676 17.2.1 问题 676 17.2.2 解决方案 677 17.2.3 工作原理 677 17.3 在Spring中访问遗留的EJB 2.x组件 683 17.3.1 问题 683 17.3.2 解决方案 683 17.3.3 工作原理 684 17.4 在Spring中创建EJB 3.0组件 687 17.4.1 问题 687 17.4.2 解决方案 687 17.4.3 工作原理 688 17.5 在Spring中访问EJB 3.0组件 689 17.5.1 问题 689 17.5.2 解决方案 690 17.5.3 工作原理 690 17.6 通过HTTP暴露和调用服务 692 17.6.1 问题 692 17.6.2 解决方案 692 17.6.3 工作原理 692 17.7 选择SOAP Web服务开发方法 696 17.7.1 问题 696 17.7.2 解决方案 696 17.7.3 工作原理 696 17.8 使用JAX-WS暴露和调用Contract-Last SOAP Web服务 698 17.8.1 问题 698 17.8.2 解决方案 698 17.8.3 工作原理 698 17.9 定义Web服务契约 705 17.9.1 问题 705 17.9.2 解决方案 705 17.9.3 工作原理 705 17.10 使用Spring-WS实现Web服务 709 17.10.1 问题 709 17.10.2 解决方案 709 17.10.3 工作原理 710 17.11 使用Spring-WS调用Web服务 715 17.11.1 问题 715 17.11.2 解决方案 715 17.11.3 工作原理 715 17.12 用XML编组开发Web服务 719 17.12.1 问题 719 17.12.2 解决方案 719 17.12.3 工作原理 720 17.13 用注解创建服务端点 724 17.13.1 问题 724 17.13.2 解决方案 725 17.13.3 工作原理 725 17.14 小结 726 第18章 企业中的Spring 727 18.1 将Spring Bean输出为JMX MBean 727 18.1.1 问题 727 18.1.2 解决方案 728 18.1.3 工作原理 728 18.2 发布和监听JMX通知 740 18.2.1 问题 740 18.2.2 解决方案 740 18.2.3 工作原理 740 18.3 在Spring中访问远程JMX MBean 742 18.3.1 问题 742 18.3.2 解决方案 742 18.3.3 工作原理 742 18.4 用Spring电子邮件支持发送邮件 745 18.4.1 问题 745 18.4.2 解决方案 745 18.4.3 工作原理 746 18.5 用Spring的Quartz支持进行调度 753 18.5.1 问题 753 18.5.2 解决方案 753 18.5.3 工作原理 753 18.6 用Spring 3.0的调度命名空间进行调度 758 18.6.1 问题 758 18.6.2 解决方案 758 18.6.3 工作原理 758 18.7 小结 762 第19章 消息 763 19.1 用Spring发送和接收JMS消息 764 19.1.1 问题 764 19.1.2 解决方案 765 19.1.3 工作原理 765 19.2 转换JMS消息 776 19.2.1 问题 776 19.2.2 解决方案 776 19.2.3 方法 776 19.3 管理JMS事务 778 19.3.1 问题 778 19.3.2 方法 779 19.3.3 解决方案 779 19.4 在Spring中创建消息驱动POJO 780 19.4.1 问题 780 19.4.2 解决方案 780 19.4.3 工作原理 781 19.5 建立连接 786 19.5.1 问题 786 19.5.2 解决方案 787 19.5.3 工作原理 787 19.6 小结 788 第20章 Spring Integration 789 20.1 用EAI集成一个系统到另一个系统 790 20.1.1 问题 790 20.1.2 解决方案 790 20.1.3 工作原理 790 20.2 使用JMS集成两个系统 793 20.2.1 问题 793 20.2.2 解决方案 793 20.2.3 工作原理 793 20.3 查询Spring Integration消息得到上下文信息 797 20.3.1 问题 797 20.3.2 解决方案 797 20.3.3 工作原理 797 20.4 用一个文件系统集成两个系统 800 20.4.1 问题 800 20.4.2 解决方案 800 20.4.3 工作原理 800 20.5 将消息从一种类型转换为另一种类型 802 20.5.1 问题 802 20.5.2 解决方案 802 20.5.3 工作原理 803 20.6 使用Spring Integration进行错误处理 806 20.6.1 问题 806 20.6.2 解决方案 806 20.6.3 工作原理 806 20.7 集成控制分支:分解器和聚合器 809 20.7.1 问题 809 20.7.2 解决方案 809 20.7.3 工作原理 809 20.8 用路由器实现条件路由 813 20.8.1 问题 813 20.8.2 解决方案 813 20.8.3 工作原理 813 20.9 使外部系统适应总线 814 20.9.1 问题 814 20.9.2 解决方案 814 20.9.3 工作原理 814 20.10 用Spring Batch产生事件 825 20.10.1 问题 825 20.10.2 解决方案 825 20.10.3 工作原理 825 20.11 使用网关 826 20.11.1 问题 826 20.11.2 解决方案 826 20.11.3 工作原理 827 20.12 小结 832 第21章 Spring Batch 834 21.1 建立Spring Batch的基础架构 836 21.1.1 问题 836 21.1.2 解决方案 836 21.1.3 工作原理 837 21.2 读取和写入(无计算) 839 21.2.1 问题 839 21.2.2 解决方案 839 21.2.3 工作原理 840 21.3 编写自定义ItemWriter和ItemReader 844 21.3.1 问题 844 21.3.2 解决方案 844 21.3.3 工作原理 844 21.4 在写入前处理输入 847 21.4.1 问题 847 21.4.2 解决方案 847 21.4.3 工作原理 847 21.5 通过事务改善生活 850 21.5.1 问题 850 21.5.2 解决方案 850 21.5.3 工作原理 850 21.6 重试 852 21.6.1 问题 852 21.6.2 解决方案 852 21.6.3 工作原理 852 21.7 控制步骤异常 855 21.7.1 问题 855 21.7.2 解决方案 856 21.7.3 工作原理 856 21.8 启动一个作业 860 21.8.1 问题 860 21.8.2 解决方案 860 21.8.3 工作原理 860 21.9 参数化一个作业 864 21.9.1 问题 864 21.9.2 解决方案 864 21.9.3 工作原理 864 21.10 小结 866 第22章 网格上的Spring 867 22.1 使用Terracotta聚合对象状态 869 22.1.1 问题 869 22.1.2 解决方案 869 22.1.3 工作原理 869 22.2 将执行分布到网格上 879 22.2.1 问题 879 22.2.2 解决方案 879 22.2.3 方法 879 22.3 方法的负载平衡 880 22.3.1 问题 880 22.3.2 解决方案 881 22.3.3 方法 881 22.4 并行处理 884 22.4.1 问题 884 22.4.2 解决方案 885 22.4.3 方法 885 22.5 在GridGain上部署 887 22.5.1 问题 887 22.5.2 解决方案 887 22.5.3 工作原理 887 22.6 小结 891 第23章 jBPM和Spring 893 软件过程 894 23.1 理解工作流模型 896 23.1.1 问题 896 23.1.2 解决方案 897 23.1.3 工作原理 897 23.2 安装jBPM 898 23.2.1 问题 898 23.2.2 解决方案 898 23.2.3 工作原理 898 23.3 将jBPM4与Spring整合 900 23.3.1 问题 900 23.3.2 解决方案 900 23.3.3 工作原理 900 23.4 用Spring构建一个服务 906 23.4.1 问题 906 23.4.2 解决方案 906 23.4.3 工作原理 907 23.5 构建业务过程 910 23.5.1 问题 910 23.5.2 解决方案 910 23.5.3 工作原理 910 23.6 小结 913 第24章 OSGi和Spring 914 24.1 OSGi入门 915 24.1.1 问题 915 24.1.2 解决方案 915 24.1.3 工作原理 916 24.2 开始使用Spring Dynamic Modules 922 24.2.1 问题 922 24.2.2 解决方案 922 24.2.3 工作原理 922 24.3 用Spring Dynamic Modules输出服务 926 24.3.1 问题 926 24.3.2 解决方案 926 24.3.3 工作原理 926 24.4 在OSGi注册表中寻找一个具体服务 929 24.4.1 问题 929 24.4.2 解决方案 930 24.4.3 工作原理 930 24.5 发布多个接口的一个服务 932 24.5.1 问题 932 24.5.2 解决方案 932 24.5.3 工作原理 932 24.6 定制Spring Dynamic Modules 933 24.6.1 问题 933 24.6.2 解决方案 933 24.6.3 工作原理 933 24.7 使用SpringSource dm Server 935 24.7.1 问题 935 24.7.2 解决方案 935 24.7.3 工作原理 935 24.8 SpringSource的各类工具 937 24.8.1 问题 937 24.8.2 解决方案 937 24.8.3 工作原理 937 24.9 小结 938 文摘 版权页:
随着Spring框架最新版本——3.0版的发布,Spring平台已经发展成熟,成为JavaJava虚拟机、Groovy、NET或者Action-Script开发人员最强大、最具革命性的解决方案之一。 《Spring攻略(第2版)》是Spring平台的深入指南,它引导你进入Spring 3及其辅助框架的最新技术。《Spring攻略(第2版)》不仅为你全面而又深入地讲解各种概念,并且在每一章中都配备了一系列详细的代码示例,以帮助读者在实际的工作中迅速应用于实战。 SpringSource为核心框架添加了许多部件。这些部件不仅简化了Java EE之上的API,并且为Java EE所忽略的问题提供了第一流的完整解决方案。构建于Spring IoC容器组件模型之上的这些Spring3部件提供了集成、批处理、OSGi、Ajax和Flex集成、状态式的Web应用、REST风格Web服务、富客户端用户界面、Google AppEngine开发、基于云的部署、消息、数据访问、Web服务等多种功能。而且,Spring能很好地与其他辅助框架(包括业务过程管理、群集缓冲以及网格计算)进行协作。 你在寻求和Ruby on Rails一样的一体化架构吗?那么你会被Grails等Spring替代方案所深深吸引,对于Groovy开发人员来说,Grails具有难以置信的能力和生产率。如果你是寻求快速、轻量级的应用构建方法的Java开发人员,你会喜欢上Spring Roo,它能让你快速地通过应用的原型阶段,进入维护阶段,形成清晰的、面向最佳实践的代码。 以上所有这些主题,在这本以丰富代码为基础的攻略中都能找到。我们希望你能够享受Spring平台的学习和使用。 Gary Mak,Josh Long和Daniel Rubio。 作者简介 作者:(美国)麦克(Gary Mak) (美国)隆(Josh Long) (美国)卢比奥(Daniel Rubio) 译者:陈宗恒 姚军 蒋亮 麦克,Gary Mak,Meta-Archit软件技术有限公司的创立者及首席顾问。 隆,Josh Long,SpringSource的Spring开发倡导人。 卢比奥,Daniel Rubio,超过10年的企业级和Web开发经验顾问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值