第九章 Spring5 高级应用及核心原理(一)

一、Spring 框架高级应用

1.1 Spring 简介
Spring 框架是一个开放源代码的 J2EE 应用程序框架,由 Rod Johnson 发起,是针对 bean 的生命周期进行管理的轻量级容器(lightweight container)。
 
Spring 解决了开发者在 J2EE 开发中遇到的许多常见的问题,提供了功能强大 IOC、AOP 及 Web MVC 等功能。Spring 可以单独应用于构筑应用程序,也可以和 Struts、Webwork、Tapestry 等众多 Web 框架组合使用,并且可以与 Swing 等桌面应用程序 AP 组合。因此, Spring 不仅仅能应用于 J2EE 应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。
  
Spring 框架主要由七部分组成,分别是 Spring Core、Spring AOP、Spring ORM、Spring DAO、Spring Context、 Spring Web 和 Spring Web MVC。
  
Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson 的程序员在 2002 年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。 Spring 是一个开源容器框架,它集成各类型的工具,通过核心的 Bean factory 实现了底层的类的实例化和生命周期的管理。在整个框架中,各类型的功能被抽象成一个个的 Bean,这样就可以实现各种功能的管理,包括动态加载和切面编程。
  
Spring 是独特的,因为若干个原因:
- 它定位的领域是许多其他流行的 framework 没有的。Spring 致力于提供一种方法管理你的业务对象。
- Spring 是全面的和模块化的。Spring 有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。例如,你可能选择仅仅使用 Spring 来简单化 JDBC 的使用,或用来管理所有的业务对象。
- 它的设计从底部帮助你编写易于测试的代码。Spring 是用于测试驱动工程的理想的 framework。
- Spring 对你的工程来说,它不需要一个以上的 framework。Spring 是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构。它也涉及到其他 framework 没有考虑到的内容。
  
1.2 Spring 框架特性
轻量:从大小与开销两方面而言 Spring 都是轻量的。完整的 Spring 框架可以在一个大小只有 1MB 多的 JAR 文件里发布。并且 Spring 所需的处理开销也是微不足道的。此外,Spring 是非侵入式的:典型地,Spring 应用中的对象不依赖于Spring 的特定类。

控制反转:Spring 通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了 IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为 IoC 与 JNDI 相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。它的底层设计模式采用了工厂模式,所有的 Bean 都需要注册到 Bean 工厂中,将其初始化和生命周期的监控交由工厂实现管理。程序员只需要按照规定的格式进行 Bean 开发,然后利用 XML 文件进行 bean 的定义和参数配置,其他的动态生成和监控就不需要调用者完成,而是统一交给了平台进行管理。 控制反转是软件设计大师 Martin Fowler 在2004年发表的 ” Inversion of Control Containers and the Dependency Injection pattern”提出的。这篇文章系统阐述了控制反转的思想,提出了控制反转有依赖查找和依赖注入实现方式。控制反转意味着在系统开发过程中,设计的类将交由容器去控制,而不是在类的内部去控制,类与类之间的关系将交由容器处理,一个类在需要调用另一个类时,只要调用另一个类在容器中注册的名字就可以得到这个类的实例,与传统的编程方式有了很大的不同,“不用你找,我来提供给你”,这就是控制反转的含义。

面向切面:Spring 提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器:Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个 bean 如何被创建——基于一个可配置原型(prototype),你的 bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring 不应该被混同于传统的重量级的 EJB 容器,它们经常是庞大与笨重的,难以使用。
框架:Spring 可以将简单的组件配置、组合成为复杂的应用。在 Spring 中,应用对象被声明式地组合,典型地是在一个 XML 文件里。Spring 也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
MVC:Spring 的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架。客户端发送请求,服务器控制器( 由DispatcherServlet 实现的)完成请求的转发,控制器调用一个用于映射的类 HandlerMapping , 该 类用于将请求映射到对应的处理器来处理请求 。HandlerMapping 将请求映射到对应的处理器 Controller(相当于 Action)在 Spring 当中如果写一些处理器组件,一般实现 Controller 接口,在 Controller 中就可以调用一些 Service 或 DAO 来进行数据操作 ModelAndView 用于存放从DAO 中取出的数据,还可以存放响应视图的一些数据。 如果想将处理结果返回给用户,那么在 Spring 框架中还提供一个视图组件 ViewResolver,该组件根据 Controller 返回的标示,找到对应的视图,将响应 response 返回给用户。
  
所有 Spring 的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为 Spring 中的各种模块提供了基础支持。
  
强大的基于 JavaBeans 的采用控制反转(Inversion of Control,IoC)原则的配置管理,使得应用程序的组件更加快捷简易。一个可用于从 applet 到 Java EE 等不同运行环境的核心 Bean 工厂。
  
数据库事务的一般化抽象层,允许宣告式(Declarative)事务管理器,简化事务的划分使之与底层无关。
 
内建的针对 JTA 和 单个 JDBC 数据源的一般化策略,使 Spring 的事务支持不要求 Java EE 环境,这与一般的 JTA 或者 EJB CMT 相反。
 
JDBC 抽象层提供了有针对性的异常等级(不再从 SQL 异常中提取原始代码),简化了错误处理,大大减少了程序员的编码量。 再次利用 JDBC 时,你无需再写出另一个 '终止' (finally) 模块。并且面向 JDBC 的异常与 Spring 通用数据访问对象(Data Access Object) 异常等级相一致。
  
以资源容器,DAO 实现和事务策略等形式与 Hibernate,JDO 和 iBATIS SQL Maps 集成。利用众多的反转控制方便特性来全面支持, 解决了许多典型的 Hibernate 集成问题。所有这些全部遵从 Spring 通用事务处理和通用数据访问对象异常等级规范。
  
灵活的基于核心 Spring 功能的 MVC 网页应用程序框架。开发者通过策略接口将拥有对该框架的高度控制,因而该框架将适应于多种呈现(View)技术,例如 JSP,FreeMarker,Velocity,Tiles,iText 以及 POI。值得注意的是,Spring 中间层可以轻易地结合于任何基于 MVC 框架的网页层,例如 Struts,WebWork,或Tapestry。
 
提供诸如事务管理等服务的面向切面编程(AOP)框架。
   
1.3 Spring 的特点
1.方便解耦,简化开发
通过 Spring 提供的 IoC 容器,我们可以将对象之间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。有了 Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
 
2.AOP 编程的支持
通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。
   
3.声明式事务的支持
在 Spring 中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
  

4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在 Spring 里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序。
  
5.方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,相反,Spring 可以降低各种框架的使用难度,Spring 提供了对各种优秀框架(如 Struts,Hibernate、Hessian、Quartz)等的直接支持。
  
6.降低 Java EE API 的使用难度
Spring 对很多难用的 Java EE API(如 JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过 Spring 的简易封装,这些 Java EE API 的使用难度大为降低。
  
7.Java 源码是经典学习范例
Spring 的源码设计精妙、结构清晰、匠心独运,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。Spring 框架源码无疑是 Java 技术的最佳实践范例。如果想在短时间内迅速提高自己的 Java 技术水平和应用开发水平,学习和研究 Spring 源码将会使你收到意想不到的效果。
  
1.4 Spring 的优点
1. 低侵入式设计,代码污染极低;
2. 独立于各种应用服务器,基于 Spring 框架的应用,可以真正实现 Write Once,Run Anywhere 的承诺;
3. Spring 的 DI 机制降低了业务对象替换的复杂性,提高了组件之间的解耦;
4. Spring 的 AOP 支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用;
5. Spring 的 ORM 和 DAO 提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问;
6. Spring 并不强制应用完全依赖于 Spring,开发者可自由选用 Spring 框架的部分或全部。
  
1.5 基本框架
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图所示:组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
1、核心容器:核心容器提供 Spring 框架的基本功能(Spring Core)。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开 [3] 。
2、Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
3、Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
4、Spring DAO:JDBCDAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
5、Spring ORM:负责框架中对象关系映射,提供相关 ORM 接入框架的关系对象管理工具。Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
6、Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
7、Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。模型由 javabean 构成,存放于Map;视图是一个接口,负责显示模型;控制器表示逻辑代码,是 Controller 的实现。Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境(Web 或 EJB)、独立应用程序、测试环境之间重用。
  
1.6 组件
Spring 确实使你能通过最简单可行的解决办法来解决你的问题,有很大实用的价值。同时他的源代码的设计理念也受到很多程序员的追捧,简洁,易用。
1. Spring 中的事务处理
2. IoC 容器在 Web 容器中的启动
3. Spring JDBC
4. Spring MVC
5. Spring AOP 获取 Proxy
6. Spring 声明式事务处理
7. Spring AOP 中对拦截器调用的实现
8. Spring 驱动 Hibernate 的实现
9. Spring Acegi 框架鉴权的实现
  
IOC 和 AOP
控制反转模式(也称作依赖性注入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器 (在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。下表列出了 IOC 的一个实现模式。
|        |                                                              |
| ------ | ------------------------------------------------------------ |
| 类型 1 | 服务需要实现专门的接口,通过接口,由对象提供这些服务,可以从对象查询依赖性(例如,需要的附加服务)【接口注入】。 |
| 类型 2 | 通过 JavaBean 的属性(例如 setter 方法)分配依赖性【setter方法注入】。 |
| 类型 3 | 依赖性以构造函数的形式提供,不以 JavaBean 属性的形式公开【构造器注入】。 |
    
Spring 框架的 IOC 容器采用类型 2 和类型 3 实现。
面向切面的编程,即 AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 Spring AOP 编写的应用程序代码是松散耦合的。
AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。
AOP 编程方面,Spring 提供了很多特性,例如 PointCut,Advice,Advisor 粗略来说就是事务管理、日志和其他各种特性切入地点。
  
1.7 容器
Spring 设计的核心是 org.springframework.beans 包,它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。BeanFactory 支持两个对象模型:
1. 单态模型提供了具有特定名称的对象的共享实例,可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。
2. 原型模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时,原型模型最适合。bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。
  

二、基于 XML 配置文件的实现

2.1 基本使用
2.1.1 创建 Maven 工程
1. 点击【Create New Project】或者

  
2. 点击【Maven】,后再点击【Next】按钮;

  
3. 设置【GroupId】和【ArtifactId】,然后点击【Next】按钮;

  
4. 指定【Project location】,然后点击【Finish】按钮;

  
5. 创建 Maven 项目成功。

  
2.1.2 添加依赖
1. 添加 Spring 依赖项
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.17.RELEASE</version>
    </dependency>
</dependencies>
   
2. 添加 junit 依赖项
<dependencies>
    <!-- Spring相关依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.17.RELEASE</version>
    </dependency>

    <!-- junit 测试依赖 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>
  
3. 添加 Spring 配置文件
右击【resources】-->【New】-->【XML Configuration File】-->【Spring Config】-->【New File】,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">

</beans>
   
4. 创建一个 HelloBean
   package com.gupaoedu.pojo;
   
   public class HelloBean {
   
       public HelloBean() {
           System.out.println("HelloBean 无参构造被执行了......");
       }
   
       public void sayHello() {
           System.out.println("Hello World! ");
       }
   
   }
  
5. 注册 Bean
   <?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 -->
       <bean id="userBean" class="com.gupaoedu.pojo.HelloBean" />
   </beans>
  
6. 测试
   package com.gupaoedu.test;
   
   import com.gupaoedu.pojo.HelloBean;
   import org.junit.Test;
   import org.springframework.context.ApplicationContext;
   import org.springframework.context.support.ClassPathXmlApplicationContext;
   
   public class HelloTest {
   
       @Test
       public void test() {
           ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
           HelloBean hello = (HelloBean)ac.getBean("userBean");
           hello.sayHello();
       }
   }
  
2.1.3 从容器中获取对象的方式
2.1.3.1 根据 id 获取
只能声明一个 id
<?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 -->
    <bean id="userBean1,userBean2" class="com.gupaoedu.pojo.HelloBean" />
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.HelloBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloBean hello = (HelloBean)ac.getBean("userBean1,userBean2");
        hello.sayHello();
    }
}
  
2.1.3.2 根据name获取
可以声明一个或者多个name,多个name之间可以用','(逗号)、';'(分号)、' '(空格)隔开。
<?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 -->
    <bean id="userBean1,userBean2" name="ub1,bu2" class="com.gupaoedu.pojo.HelloBean" />
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.HelloBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloBean h1 = (HelloBean)ac.getBean("ub1");
        HelloBean h2 = (HelloBean)ac.getBean("ub2");
        h1.sayHello();
        h2.sayHello();
    }
}
  
2.1.3.3 根据类型获取
<?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 -->
    <bean id="userBean1,userBean2" name="ub1,bu2" class="com.gupaoedu.pojo.HelloBean" />
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.HelloBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloBean hello = ac.getBean(HelloBean.class);
        hello.sayHello();
    }
}
  
2.1.3.4 组合条件查找
<?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 -->
    <bean id="userBean1,userBean2" name="ub1,ub2" class="com.gupaoedu.pojo.HelloBean" />
    <bean id="userBean3,userBean4" name="ub3,ub4" class="com.gupaoedu.pojo.HelloBean" />
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.HelloBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloBean hello = ac.getBean("ub1", HelloBean.class);
        hello.sayHello();
    }
}
  
2.1.4 BeanFactory 和 ApplicationContext 的区别
- 两者属于不同的包
- BeanFactory 和 ApplicationContext 都是属于 Spring 下的顶级接口,其中 BeanFactory 提供了基础的访问容器的能⼒,ApplicationContext 属于 BeanFactory 的子类,BeanFactory 所有的功能 ApplicationContext 也是拥有,
除此之外 ApplicationContext 还有用其他 BeanFactory 没有的功能,例如:对国际化的支持,支持资源的访问,支持事件的传播等。
- 对于执行性能来说,ApplicationContext 是一次性加载并初始化所有的 bean 的,所以它的启动过程可能比较慢,但是后续的执行比较快;而 BeanFactory 是需要哪个类才去加载那个类,因此 BeanFactory 占用的系统资源更少,启动更快,但后续的执行可能会慢一些。
  
2.1.5 工厂注入
通过外部方式来创建依赖对象的方式叫做注入。
  
2.1.5.1 静态工厂注入
<?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 class="com.gupaoedu.com.gupaoedu.factory.StaticFactoryDemo" factory-method="getInstance" id="hello" />
</beans>
package com.gupaoedu.com.gupaoedu.factory;

import com.gupaoedu.pojo.HelloBean;
import java.util.HashMap;
import java.util.Map;

public class StaticFactory {

    public static Map<String, HelloBean> hashMap ;

    static {
        hashMap = new HashMap<String, HelloBean>();
        hashMap.put("h1",new HelloBean());
        hashMap.put("h2",new HelloBean());
        hashMap.put("h3",new HelloBean());
    }

    public static HelloBean getInstance(){
        return hashMap.get("h1");
    }
    
}
  
2.1.5.2 动态工厂注入
<?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 class="com.gupaoedu.com.gupaoedu.factory.DynamicFactoryDemo" id="dynamicFactoryDemo" />

    <!-- 从工程费对象中获取 需要的对象 -->
    <bean id="hello2" factory-bean="dynamicFactoryDemo" factory-method="getInstanc" />
</beans>
package com.gupaoedu.com.gupaoedu.factory;

import com.gupaoedu.pojo.HelloBean;

public class DynamicFactoryDemo {

    public HelloBean getInstanc() {
        return new HelloBean();
    }

}
  
2.1.6 属性注入(DI)
2.1.6.1 构造方法注入
通过构造方法注入,提供对应的构造方法,可以通过name或index来指定要赋值的参数。
package com.gupaoedu.pojo;

public class UserBean {

    private Integer id;
    private String userName;

    public UserBean() {
    }

    public UserBean(Integer id, String userName) {
        this.id = id;
        this.userName = userName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

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

    @Override
    public String toString() {
        return "UserBean{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                '}';
    }
}
<?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 class="com.gupaoedu.pojo.UserBean" id="user">
        <!-- 构造注入 - 通过name赋值 -->
        <constructor-arg name="id" value="1" />
        <constructor-arg name="userName" value="张三 " />
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user);
    }
}
<?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 class="com.gupaoedu.pojo.UserBean" id="user">
        <!-- 构造注入 - 通过name赋值 -->
        <!--<constructor-arg name="id" value="1" />
        <constructor-arg name="userName" value="张三 " />-->
        <!-- 构造注入 - 通过index赋值 -->
        <constructor-arg index="0" value="2" />
        <constructor-arg index="1" value="李四" />
    </bean>
</beans>
  
简化操作
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean class="com.gupaoedu.pojo.UserBean" id="user" c:_0="4" c:_1="赵六"/>
</beans>
  
2.1.6.2 set 方法注入
属性字段提供 set 方法,在配置文件中通过 property 属性指定属性字段。
<?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 class="com.gupaoedu.pojo.UserBean" id="user">
        <!-- set注入 -->
        <property name="id" value="3"/>
        <property name="userName" value="王五"/>
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user);
    }
}
  
简化操作
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean class="com.gupaoedu.pojo.UserBean" id="user" p:id="5" p:userName="孙七"/>
</beans>
  
2.1.7 其他注入
2.1.7.1 自定义类型
package com.gupaoedu.pojo;

public class Cat {

    private String nick;
    private String color;

    public String getNick() {
        return nick;
    }

    public void setNick(String nick) {
        this.nick = nick;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Cat() {
    }

    public Cat(String nick, String color) {
        this.nick = nick;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "nick='" + nick + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}
package com.gupaoedu.pojo;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class UserBean {

    private Integer id;
    private String userName;
    private Cat cat;
    private String[] favorites;
    private List<Cat> cats;
    private Map<String, Object> map;
    private Properties props;

    public UserBean() {
    }

    public UserBean(Integer id, String userName) {
        this.id = id;
        this.userName = userName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

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

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public String[] getFavorites() {
        return favorites;
    }

    public void setFavorites(String[] favorites) {
        this.favorites = favorites;
    }

    public List<Cat> getCats() {
        return cats;
    }

    public void setCats(List<Cat> cats) {
        this.cats = cats;
    }

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", cat=" + cat +
                ", favorites=" + Arrays.toString(favorites) +
                ", cats=" + cats +
                ", map=" + map +
                ", props=" + props +
                '}';
    }
}
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" id="cat" />
    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat" ref="cat">
            <!--<bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />-->
        </property>
    </bean>
</beans>
  
等价于
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat">
            <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />
        </property>
    </bean>
</beans>
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat">
            <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />
        </property>
        <property name="favorites">
            <array>
                <value>游戏</value>
                <value>音乐</value>
                <value>看书</value>
            </array>
        </property>
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user.getCat());
        String[] favorites = user.getFavorites();
        for(String f : favorites) {
            System.out.println(f);
        }
    }
}
  
2.1.7.2 数组
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat">
            <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />
        </property>
        <property name="favorites">
            <array>
                <value>游戏</value>
                <value>音乐</value>
                <value>看书</value>
            </array>
        </property>
        <property name="cats">
            <list>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="小白" p:color="白色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="毛团" p:color="灰色"/>
            </list>
        </property>
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user.getCat());
        String[] favorites = user.getFavorites();
        for(String f:favorites) {
            System.out.println(f);
        }
        System.out.println(user.getCats());
    }
}
  
2.1.7.3 Map
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat">
            <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />
        </property>
        <property name="favorites">
            <array>
                <value>游戏</value>
                <value>音乐</value>
                <value>看书</value>
            </array>
        </property>
        <property name="cats">
            <list>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="小白" p:color="白色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="毛团" p:color="灰色"/>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="name1" value="张三"/>
                <entry key="name2" value="李四"/>
                <entry key="name3" value="王五"/>
            </map>
        </property>
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Set;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user.getCat());
        String[] favorites = user.getFavorites();
        for(String f:favorites) {
            System.out.println(f);
        }
        System.out.println(user.getCats());
        Set<String> maps = user.getMap().keySet();
        for(String key:maps) {
            System.out.println(key + ":" + user.getMap().get(key));
        }
    }
}
  
2.1.7.4 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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.gupaoedu.pojo.UserBean" id="user">
        <property name="cat">
            <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色" />
        </property>
        <property name="favorites">
            <array>
                <value>游戏</value>
                <value>音乐</value>
                <value>看书</value>
            </array>
        </property>
        <property name="cats">
            <list>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="花花" p:color="黑色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="小白" p:color="白色"/>
                <bean class="com.gupaoedu.pojo.Cat" p:nick="毛团" p:color="灰色"/>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="name1" value="张三"/>
                <entry key="name2" value="李四"/>
                <entry key="name3" value="王五"/>
            </map>
        </property>
        <property name="props">
            <props>
                <prop key="username">root</prop>
                <prop key="password">1234</prop>
            </props>
        </property>
    </bean>
</beans>
package com.gupaoedu.test;

import com.gupaoedu.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Properties;
import java.util.Set;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-01.xml");
        UserBean user = ac.getBean("user", UserBean.class);
        System.out.println(user.getCat());
        String[] favorites = user.getFavorites();
        for(String f:favorites) {
            System.out.println(f);
        }
        System.out.println(user.getCats());
        Set<String> maps = user.getMap().keySet();
        for(String key:maps) {
            System.out.println(key + ":" + user.getMap().get(key));
        }
        Properties props = user.getProps();
        System.out.println(props.getProperty("username"));
        System.out.println(props.getProperty("password"));
    }
}
  

三、基于注解编程

3.1 综合案例
Java 配置类
package com.gupaoedu;

import com.gupaoedu.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {

    /**
     * @Bean 作用相当于applicationContext.xml中的<bean>
     * 默认的name是方法名称
     * 自定义的name 可以通过value属性或者name属性来指定
     * @return
     */
    @Bean(name = {"aaa","bbb"})
    public User getUser() {
        return new User();
    }

}
  
测试方法
package com.gupaoedu.test;

import com.gupaoedu.JavaConfig;
import com.gupaoedu.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainTest {

    @Test
    public void test() {
        // 通过@Configuration注解来初始化IoC容器
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        System.out.println(ac.getBean("bbb", User.class));
    }

}
   
3.1.1 基于 XML 方式的实现
package com.gupaoedu.pojo;

public class User {

    private Integer id;
    private String userName;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

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

    public User() {
    }

    public User(Integer id, String userName) {
        this.id = id;
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                '}';
    }
}
package com.gupaoedu.controller;

import com.gupaoedu.pojo.User;
import com.gupaoedu.service.IUserService;

import java.util.List;

public class UserController {

    private IUserService userService;

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    public List<User> query(){
        return userService.query();
    }

}
package com.gupaoedu.dao;

import com.gupaoedu.pojo.User;
import java.util.List;

public interface IUserDao {

    public List<User> query();

}

package com.gupaoedu.dao.impl;

import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.pojo.User;
import java.util.Arrays;
import java.util.List;

public class UserDaoImpl implements IUserDao {
    public List<User> query() {
        return Arrays.asList(
                new User(1, "张三"),
                new User(2, "李四"),
                new User(3, "王五"),
                new User(4, "赵六"));
    }
}
package com.gupaoedu.service;

import com.gupaoedu.pojo.User;
import java.util.List;

public interface IUserService {

    public List<User> query();

}
package com.gupaoedu.service.impl;

import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.pojo.User;
import com.gupaoedu.service.IUserService;
import java.util.List;

public class UserServiceImpl implements IUserService {

    private IUserDao userDao;

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    public List<User> query() {
        return userDao.query();
    }
}
<?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">

    <!-- 将Dao对象注册到容器中 -->
    <bean class="com.gupaoedu.dao.impl.UserDaoImpl" id="userDao"></bean>

    <!-- 将Service对象注册到容器中 -->
    <bean class="com.gupaoedu.service.impl.UserServiceImpl" id="userService">
        <!-- 通过Set注入的方式引入Dao对象 -->
        <property name="userDao" ref="userDao" />
    </bean>

    <!-- 将Controller对象注册到容器中 -->
    <bean class="com.gupaoedu.controller.UserController">
        <!-- 通过Set注入的方式引入Service对象 -->
        <property name="userService" ref="userService" />
    </bean>

</beans>
package com.gupaoedu;

import com.gupaoedu.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppStarter {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserController bean = ac.getBean(UserController.class);
        System.out.println(bean.query());
    }

}
  
3.1.2 基于 Java 配置的方式实现
package com.gupaoedu.pojo;

public class User {

    private Integer id;
    private String userName;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

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

    public User() {
    }

    public User(Integer id, String userName) {
        this.id = id;
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                '}';
    }
}
package com.gupaoedu.controller;

import com.gupaoedu.pojo.User;
import com.gupaoedu.service.IUserService;

import java.util.List;

public class UserController {

    private IUserService userService;

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    public List<User> query(){
        return userService.query();
    }

}
package com.gupaoedu.dao;

import com.gupaoedu.pojo.User;
import java.util.List;

public interface IUserDao {

    public List<User> query();

}
package com.gupaoedu.dao.impl;

import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.pojo.User;
import java.util.Arrays;
import java.util.List;

public class UserDaoImpl implements IUserDao {
    public List<User> query() {
        return Arrays.asList(
                new User(1, "张三"),
                new User(2, "李四"),
                new User(3, "王五"),
                new User(4, "赵六"));
    }
}

package com.gupaoedu.service;

import com.gupaoedu.pojo.User;
import java.util.List;

public interface IUserService {

    public List<User> query();

}
package com.gupaoedu.service.impl;

import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.pojo.User;
import com.gupaoedu.service.IUserService;
import java.util.List;

public class UserServiceImpl implements IUserService {

    private IUserDao userDao;

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    public List<User> query() {
        return userDao.query();
    }
}
package com.gupaoedu;

import com.gupaoedu.controller.UserController;
import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.dao.impl.UserDaoImpl;
import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {

    @Bean
    public IUserDao userDao() {
        return new UserDaoImpl();
    }

    @Bean
    public IUserService userService(IUserDao userDao) {
        IUserService userService = new UserServiceImpl();
        ((UserServiceImpl) userService).setUserDao(userDao);
        return userService;
    }

    @Bean
    public UserController userController(IUserService userService) {
        UserController userController = new UserController();
        userController.setUserService(userService);
        return userController;
    }
}
package com.gupaoedu;

import com.gupaoedu.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppStarter {
    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        System.out.println(ac.getBean(UserController.class).query());
    }
}
  
3.2 注解
3.2.1 配置注解
| 注解名称       | 说明                                                         |
| -------------- | ------------------------------------------------------------ |
| @Configuration | 把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 |
| @ComponentScan | 在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan> |
| @Scope         | 用于指定scope作用域的(用在类上)                            |
| @Lazy          | 表示延迟初始化                                               |
| @Conditional   | Spring4开始提供,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。 |
| @Import        | 导入外部资源                                                 |
| 生命周期控制   | @PostConstruct用于指定初始化方法(用在方法上)@PreDestory用于指定销毁方法(用在方法上)@DependsOn:定义Bean初始化及销毁时的顺序 |
  
扩展:SpringBoot 中的 ConditionalXXX
| @Conditional扩展注解            | 作用(判断是否满足当前指定条件)                   |
| ------------------------------- | ------------------------------------------------ |
| @ConditionalOnJava              | 系统的Java版本是否符合要全                       |
| @ConditionalOnBean              | 容器中存在指定的Bean                             |
| @ConditionalOnMissingBean       | 容器中不存在指定的Bean                           |
| @ConditionalOnExpression        | 满足SpEL表达式                                   |
| @ConditionalOnClass             | 系统中有指定的类                                 |
| @ConditionalOnMissingClass      | 系统中没有指定的类                               |
| @ConditionalOnSingleCandidate   | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
| @ConditionalOnProperty          | 系统中指定的属性是否有指定的值                   |
| @ConditionalOnResource          | 类路径下是否存在指定的资源文件                   |
| @ConditionalOnWebApplication    | 当前是Web环境                                    |
| @ConditionalOnNotWebApplication | 当前不是Web环境                                  |
| @ConditionalOnJndi              | JNDI存在指定项                                   |
  
3.2.2 赋值注解
| 注解名称        | 说明                                                         |
| --------------- | ------------------------------------------------------------ |
| @Component      | 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 |
| @Service        | 用于标注业务层组件                                           |
| @Controller     | 用于标注控制层组件                                           |
| @Repository     | 用于标注数据访问组件,即DAO组件。                            |
| @Value          | 普通数据类型赋值                                             |
| @Autowired      | 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用 |
| @PropertySource | 读取配置文件赋值                                             |
| @Qualifier      | 如存在多个实例配合使用                                       |
| @Primary        | 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 |
| @Resource       | 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。     |
  
3.3 注解编程的使用
通过@Componenet 注解标注
 
3.3.1 基于 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
">


    <!-- 添加扫描的路径 指定从哪些package下加载被 @Component标注的类型-->
    <!--<context:component-scan base-package="com.gupaoedu"/>-->
    <!--<context:component-scan base-package="com.gupaoedu.controller
    ,com.gupaoedu.service.impl
    ,com.gupaoedu.dao.impl"/>-->
    <context:component-scan base-package="com.gupaoedu.controller" />
    <context:component-scan base-package="com.gupaoedu.service.impl" />
    <context:component-scan base-package="com.gupaoedu.dao.impl" />
</beans>
 
显示的限制控制层只能用@Controller注解,业务逻辑层和持久层不能使用@Controller注解。
<?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
">


    <!-- 添加扫描的路径 指定从哪些package下加载被 @Component标注的类型-->
    <!--<context:component-scan base-package="com.gupaoedu"/>-->
    <!--<context:component-scan base-package="com.gupaoedu.controller
    ,com.gupaoedu.service.impl
    ,com.gupaoedu.dao.impl"/>-->
    <!--
    use-default-filters="false" 表示不适用默认的过滤器  
        默认过滤器会识别 @Componenet @Controller @Service @Repository
    -->
    <context:component-scan base-package="com.gupaoedu.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <context:component-scan base-package="com.gupaoedu.service.impl,com.gupaoedu.dao.impl" use-default-filters="true" >
        <!-- 排除掉某个注解 -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

</beans>
  
@Autowired 和@Resource 的区别。
@Autowired:默认只能根据类型来查找,可以结合@Qualifier("abc")注解来实现通过 name 查找。
@Resource:默认同样是根据类型来查找,但是提供的有 type 和 name 属性类实现不同的查找方式。
  
3.3.2 基于 Java 配置的方式实现
我们需要在 Java 配置类中通过@ComponentScan 注解来指定扫描的路径。默认 的情 况下 扫描的 是当 前路 径及其 子路 径下 的所 有的被 @Componenet @Controller @Service @Repository 标注的类型。
package com.gupaoedu;

import com.gupaoedu.controller.UserController;
import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.dao.impl.UserDaoImpl;
import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

/**
 *  @ComponentScan 如果不去指定扫描的路基,默认是会扫描当前目录及其子目录下的所有的
 *                  被@Componenet @Controller @Service @Repository标注的类型
 */
@Configuration
/*@ComponentScan(value = {"com.gupaoedu.controller"}
,useDefaultFilters = false
        ,includeFilters = {@ComponentScan.Filter(Controller.class)})*/
@ComponentScans({
        @ComponentScan(value = {"com.gupaoedu.controller"}
                ,useDefaultFilters = false
                ,includeFilters = {@ComponentScan.Filter(Controller.class)})
        ,@ComponentScan(value = {"com.gupaoedu.service","com.gupaoedu.dao"}
                ,useDefaultFilters = true
                ,excludeFilters = {@ComponentScan.Filter(Controller.class)})
})
public class JavaConfig {

}
  
3.3.3 @Value 注解介绍
@Value 帮助我们给数组动态的设值
package com.gupaoedu.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

/**
 * 让每一个人的职业生涯不留遗憾
 *
 * @author 波波老师【咕泡学院】
 */
@Component
public class User {

    @Value("张三") // 注入普通的字符串
    private String userName ;

    @Value("#{systemProperties['os.name']}")
    private String systemPropertiesName; // 注入操作系统的信息

    @Value("#{T(java.lang.Math).random()*100}")
    private double randomNumber; // 注入表达式的结果

    @Value("#{person.personName}")
    private String fromPersonName; // 注入其他Bean的属性


    @Value("classpath:test.txt")
    private Resource resourceFile;

    @Value("http://www.baidu.com")
    private Resource baiduFile;

    public String getUserName() {
        return userName;
    }

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

    public String getSystemPropertiesName() {
        return systemPropertiesName;
    }

    public void setSystemPropertiesName(String systemPropertiesName) {
        this.systemPropertiesName = systemPropertiesName;
    }

    public double getRandomNumber() {
        return randomNumber;
    }

    public void setRandomNumber(double randomNumber) {
        this.randomNumber = randomNumber;
    }

    public String getFromPersonName() {
        return fromPersonName;
    }

    public void setFromPersonName(String fromPersonName) {
        this.fromPersonName = fromPersonName;
    }

    public Resource getResourceFile() {
        return resourceFile;
    }

    public void setResourceFile(Resource resourceFile) {
        this.resourceFile = resourceFile;
    }

    public Resource getBaiduFile() {
        return baiduFile;
    }

    public void setBaiduFile(Resource baiduFile) {
        this.baiduFile = baiduFile;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", systemPropertiesName='" + systemPropertiesName + '\'' +
                ", randomNumber=" + randomNumber +
                ", fromPersonName='" + fromPersonName + '\'' +
                ", resourceFile=" + resourceFile +
                ", baiduFile=" + baiduFile +
                '}';
    }
}
package com.gupaoedu.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person {

    @Value("PersonInfo")
    private String personName;

    public String getPersonName() {
        return personName;
    }

    public void setPersonName(String personName) {
        this.personName = personName;
    }
}
package com.gupaoedu.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.gupaoedu")
public class JavaConfig {

}
public class AppStarter {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        System.out.println(ac.getBean(User.class));
        User user = ac.getBean(User.class);
    }
}

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸之间不太闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值