05-Web技术-Spring-IOC

第13章-WEB技术-Spring-IOC

学习目标

  1. 掌握 IOC 和 DI 原理以及使用
  2. 掌握 Bean 的装配模式
  3. 掌握 Bean 的相关注解
  4. 掌握 AOP 面向切面编程原理

Spring 概述

Spring 是一个开源框架 。Spring 为简化企业级开发而生,使用 Spring,JavaBean 就可以实现很多以前要靠 EJB 才能实现的功能。同样的功能,在 EJB 中要通过繁琐的配置和复杂的代码才能够实现, 而在 Spring 中却非常的优雅和简洁。

Spring 是一个 IOC(DI)和 AOP 容器框架。

Spring 的特性

(1)非侵入式:基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API

(2) 依赖注入:DI——Dependency Injection,反转控制(IOC)最经典的实现。

(3) 面向切面编程:Aspect Oriented Programming——AOP

(4) 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期

(5) 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中 可以使用 XML 和 Java 注解组合这些对象。

Spring 模块

Spring框架的功能被有组织的分散到约20个模块中。分成几个部分

源码包:https://github.com/spring-projects/spring-framework/tags

image-20211013151912449

核心容器

  • spring-core和spring-beans模块:提供了框架的基础功能,包括IOC和依赖注入功能。 BeanFactory是一个成熟的工厂模式的实现。你不再需要编程去实现单例模式,允许你把依赖关系的配置和描述从程序逻辑中解耦。

  • spring-context上下文模块:建立在由Core和Beans模块提供的坚实的基础上:它提供一个框架式的对象访问方式,类似于一个JNDI注册表。上下文模块从Beans模块继承其功能,并添加支持国际化(使用,例如,资源集合),事件传播,资源负载,并且透明创建上下文,例如,Servlet容器。Context模块还支持Java EE的功能,如EJB,JMX和基本的远程处理。ApplicationContext接口是Context模块的焦点。

  • spring-context-support模块:支持整合普通第三方库到Spring应用程序上下文,特别是用于高速缓存(ehcache,JCache)和调度(CommonJ,Quartz)的支持。

  • spring-expression模块:提供了强大的表达式语言去支持查询和操作运行时对象图。这是对JSP 2.1规范中规定的统一表达式语言(unified EL)的扩展。该语言支持设置和获取属性值,属性分配,方法调用,访问数组,集合和索引器的内容,逻辑和算术运算,变量命名以及从Spring的IoC容器中以名称检索对象。它还支持列表投影和选择以及常见的列表聚合。

AOP和Instrumentation

  • spring-aop模块:提供了一个符合AOP联盟(要求)的面向方面的编程实现,例如,允许您定义方法拦截器和切入点(pointcuts),以便干净地解耦应该被分离的功能实现。 使用源级元数据(source-level metadata)功能,还可以以类似于.NET属性的方式将行为信息合并到代码中。

  • spring-aspects模块:单独提供了与AspectJ的集成。

  • spring-instrument模块:提供了类植入(instrumentation)支持和类加载器的实现,可以应用在特定的应用服务器中。该spring-instrument-tomcat 模块包含了支持Tomcat的植入代理。

消息

  • spring-messaging模块:(消息传递模块),其中包含来自Spring Integration的项目,例如,Message,MessageChannel,MessageHandler,和其他用来传输消息的基础应用。该模块还包括一组用于将消息映射到方法的注释(annotations),类似于基于Spring MVC注释的编程模型。

数据访问/集成

数据访问/集成层由JDBC,ORM,OXM,JMS和事务模块组成。

  • spring-jdbc模块:提供了一个JDBC –抽象层,消除了需要的繁琐的JDBC编码和数据库厂商特有的错误代码解析。

  • spring-tx模块:支持用于实现特殊接口和所有POJO(普通Java对象)的类的编程和声明式事务 管理。

  • spring-orm模块:为流行的对象关系映射(object-relational mapping )API提供集成层,包括JPA和Hibernate。使用spring-orm模块,您可以将这些O / R映射框架与Spring提供的所有其他功能结合使用,例如前面提到的简单声明性事务管理功能。

  • spring-oxm模块:提供了一个支持对象/ XML映射实现的抽象层,如JAXB,Castor,JiBX和XStream。

  • spring-jms模块:(Java Messaging Service) 包含用于生产和消费消息的功能。自Spring Framework 4.1以来,它提供了与 spring-messaging模块的集成。

Web

  • Web层由spring-web,spring-webmvc和spring-websocket 模块组成。

  • spring-web模块:提供基本的面向Web的集成功能,例如多部分文件上传功能,以及初始化一个使用了Servlet侦听器和面向Web的应用程序上下文的IoC容器。它还包含一个HTTP客户端和Spring的远程支持的Web相关部分。

  • spring-webmvc模块:(也称为Web-Servlet模块)包含用于Web应用程序的Spring的模型-视图-控制器(MVC)和REST Web Services实现。 Spring的MVC框架提供了领域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成。

测试

  • spring-test模块:支持使用JUnit或TestNG对Spring组件进行单元测试和 集成测试。它提供了Spring ApplicationContexts的一致加载和这些上下文的缓存。它还提供可用于独立测试代码的模仿(mock)对象。

Spring 项目准备

推荐使用开发工具STS

下载官网推荐开发工具STS

https://spring.io/tools3/sts/legacy

img
  1. 下载后如下:
img
  1. 解压后:
img
  1. 点击进入:
img
  1. 点击进入sts-3.9.8.RELEASE:
img
  1. 双击打开STS.exe,需要先安装JDK(EE1.8及以上)。

如果是jdk11-12,默认安装后没有jre,需要手动生成,进入jdk安装目录:

1
2
sh
 bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre

在控制台执行上面的命令即可生成。

  1. 打开软件后如下:

img

  1. 下载Maven(可选,可以使用默认的)

http://maven.apache.org/download.cgi

img

解压

img

创建项目

img img

导入核心包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
<span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>com.star<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>SpringFramework<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-title">version</span>></span>1.0-SNAPSHOT<span class="hljs-tag"></<span class="hljs-title">version</span>></span>

<span class="hljs-tag"><<span class="hljs-title">properties</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">maven.compiler.source</span>></span>11<span class="hljs-tag"></<span class="hljs-title">maven.compiler.source</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">maven.compiler.target</span>></span>11<span class="hljs-tag"></<span class="hljs-title">maven.compiler.target</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">spring.framework</span>></span>5.3.10<span class="hljs-tag"></<span class="hljs-title">spring.framework</span>></span>
<span class="hljs-tag"></<span class="hljs-title">properties</span>></span>

<span class="hljs-tag"><<span class="hljs-title">dependencies</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-core<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-beans<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-context<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-expression<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-aop<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">dependency</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-title">groupId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">artifactId</span>></span>spring-jcl<span class="hljs-tag"></<span class="hljs-title">artifactId</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">version</span>></span>${spring.framework}<span class="hljs-tag"></<span class="hljs-title">version</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">dependency</span>></span>
<span class="hljs-tag"></<span class="hljs-title">dependencies</span>></span>

</project>

也可以只导入 spring-context 会自动导入其他相关依赖

Spring IOC 和 DI

IOC

ioc (Inversion of Control) 反转控制

在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式, 增加了学习成本,同时降低了开发效率。

反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发 的效率。这种行为也称为查找的被动形式。

DI

DI (Dependency Injection) 依赖注入

DI 是 IOC 的另一种展现方式:即组件以一些预先定义好的方式(例如:parameter、construct、setter 方法)接受来自于容器的资源注入。

IOC 和 DI 的关系

IOC 控制反转是一种思想

DI 依赖注入是一种设计模式

使用 DI 依赖注入实现 IoC 控制反转

如:

在没有 IoC 之前,我们要在 A 类中使用 B 类,就要在 A 类中 new 出 B 类的实例,这样 A 类和 B 类之间就出现了耦合。

1
2
3
4
java
 public class A {
 	private B b = new B();
 }

使用了IoC之后,我们就把实例化这样操作交给框架去帮我们做了。

1
2
3
4
public class A {
	@autowire
    private B b; // 无需创建,由 bean 工厂注入到 b 变量中
}

IOC 容器

Spring 容器是创建程序中 bean 的核心,通过 DI 来协调这些对象之间的关系。

Spring 自带多个容器的实现,可以归纳为两种不同的类型:

  1. bean 工厂(BeanFactory),最简单的容器,提供基本的 DI 支持。
  2. 应用上下文(ApplicationContext),继承了(BeanFactory),并提供应用框架级别的服务。

BeanFactory管理任何类型对象的高级配置机制。 ApplicationContext

BeanFactory提供了配置框架和基本功能,并ApplicationContext添加了更多企业特定的功能。

BeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
T getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
T getBean(Class requiredType) throws BeansException;
T getBean(Class requiredType, Object... args) throws BeansException;
ObjectProvider getBeanProvider(Class requiredType);
ObjectProvider getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException; @Nullable Class getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
// 通过 BeanFactory 读取配置文件
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);// 新增 Xml阅读器
reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));// 规则注册入容

// 根据id值获取bean实例对象
User user = (User) factory.getBean("user");
// 通过类类型获取bean实例对象
User user2 = factory.getBean(User.class);
// 根据id值 和 类类型获取bean实例对象
User user3 = factory.getBean("user", User.class);
System.out.println(user);

ApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.springframework.context;

import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

Spring 自带了多种类型的应用上下文:

  • AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
  • AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
  • ClassPathXmlApplicationContext:从类路径(包含JAR文件)下的一个或多个XML配置文件中加载上下文。
  • FileSystemXmlapplicationcontext:从文件系统下的一个或多个XML配置文件中加载上下文。
  • XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文。

在后面讲解基于Web的Spring应用时,我再讲解AnnotationConfigWebApplicationContextXmlWebApplicationContext

无论是从文件系统中装载应用上下文还是从类路径下装载应用上下文,将bean加载到bean工厂的过程都是相似的。

Spring Bean 装配机制

作为开发人员,需要告诉 Spring 哪些对象要作为 bean 装配到容器中,beanbean之间的依赖关系。

Spring提供了三种主要的装配机制:

  1. XML 中进行显示配置
  2. Java 中进行显示配置
  3. 隐式的 bean 发现机制和自动装配

XML 装配 bean

ApplicationContext 接口基于XML方式的主要实现类

  • ClassPathXmlApplicationContext:对应类路径下的 XML 格式的配置文件
  • FileSystemXmlApplicationContext:对应文件系统中的 XML 格式的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 方式2:在指定的文件系统路径下查找xml文件
ApplicationContext context1 = new FileSystemXmlApplicationContext("D:/applicationContext.xml");

// 根据id值获取bean实例对象
User user = (User) context.getBean("user");
// 通过类类型获取bean实例对象
User user2 = context.getBean(User.class);
// 根据id值 和 类类型获取bean实例对象
User user3 = context.getBean("user", User.class);
System.out.println(user);

(1)创建 实体类

在 bean 包中创建 User.java 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.star.spring.bean;

public class User {
private long id;
private String name;
private int age;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">()</span> </span>{
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id, String name, <span class="hljs-keyword">int</span> age)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
    <span class="hljs-keyword">this</span>.name = name;
    <span class="hljs-keyword">this</span>.age = age;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> id;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> name;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
    <span class="hljs-keyword">this</span>.name = name;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> age;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
    <span class="hljs-keyword">this</span>.age = age;
}

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"User{"</span> +
            <span class="hljs-string">"id="</span> + id +
            <span class="hljs-string">", name='"</span> + name + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">", age="</span> + age +
            <span class="hljs-string">'}'</span>;
}

}

(2)使用 XML 文件来配置 bean 的信息

在项目中任意位置创建 xml 文件(建议在 resource 目录下),创建 applicationContext.xml (文件名任意)

setter 赋值

通过 setter 方法给 bean 的属性赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!--
    使用bean元素定义一个由IOC容器创建的对象
    class 属性指定用于创建bean的全类名
    id 属性指定用于引用bean实例的标识,唯一
 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span>></span>
    <span class="hljs-comment"><!-- 
		使用property子元素为bean的属性赋值
		如果不赋值则为变量的默认值
	--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"id"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"name"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"张三"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"age"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"20"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

默认使用 beansetter 方法赋值

image-20211013112739174

获取实体 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.star.spring;

import com.star.spring.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
public static void main(String[] args) {
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    <span class="hljs-comment">// 根据id值获取bean实例对象</span>
    User user = (User) context.getBean(<span class="hljs-string">"user"</span>);
    System.out.println(user);
}

}

输出

User{id=1, name='张三', age=20}

构造器 赋值

如果 bean 有构造函数,则可以选择使用 构造函数 给属性赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!--
    使用bean元素定义一个由IOC容器创建的对象
    class 属性指定用于创建bean的全类名
    id 属性指定用于引用bean实例的标识,唯一
 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span>></span>
    <span class="hljs-comment"><!-- 
        通过有参构造函数 为 bean 属性赋值
        如果和 bean 同时使用 优先使用 构造函数
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"李四"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"20"</span>/></span>

    <span class="hljs-comment"><!--
		使用property子元素为bean的属性赋值
		如果不赋值则为变量的默认值
	--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"id"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"name"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"张三"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"age"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"20"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

或者指定参数序号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!--
    使用bean元素定义一个由IOC容器创建的对象
    class 属性指定用于创建bean的全类名
    id 属性指定用于引用bean实例的标识,唯一
 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span>></span>
    <span class="hljs-comment"><!--
        通过有参构造函数 为 bean 属性赋值
        如果和 bean 同时使用 优先使用 构造函数
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"0"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"20"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"2"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"李四"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"1"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

还可以指定参数数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!--
    使用bean元素定义一个由IOC容器创建的对象
    class 属性指定用于创建bean的全类名
    id 属性指定用于引用bean实例的标识,唯一
 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span>></span>
    <span class="hljs-comment"><!--
        通过有参构造函数 为 bean 属性赋值
        如果和 bean 同时使用 优先使用 构造函数
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"0"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"long"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"20"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"2"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"int"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"李四"</span> <span class="hljs-attribute">index</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"java.lang.String"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

获取实体 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.star.spring;

import com.star.spring.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
public static void main(String[] args) {
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    <span class="hljs-comment">// 根据id值获取bean实例对象</span>
    User user = (User) context.getBean(<span class="hljs-string">"user"</span>);
    System.out.println(user);
}

}

输出

User{id=1, name='张三', age=20}

p 名称空间

为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。

Spring 从 2.5 版本开始引入了一个新的 p 命名空间,可以通过元素属性的方式配置 Bean 的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!--
    使用 p 名称空间,在顶部添加如下 名称空间
    xmlns:p="http://www.springframework.org/schema/p"
    添加属性的时候 用前缀 如: p:prop="value"
 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">p:name</span>=<span class="hljs-value">"王五"</span> <span class="hljs-attribute">p:age</span>=<span class="hljs-value">"20"</span>/></span>

</beans>

关联属性

如果类中包含另一个类,则需要在给属性赋值的时候,传入另一个对象,如下对象关系:

User -> IdCard

IdCard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.star.spring.bean;

import java.util.Date;

public class IdCard {
private long id;
private String number;
private Date statTime;
private Date endtime;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">IdCard</span><span class="hljs-params">()</span> </span>{}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">IdCard</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id, String number, Date statTime, Date endtime)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
    <span class="hljs-keyword">this</span>.number = number;
    <span class="hljs-keyword">this</span>.statTime = statTime;
    <span class="hljs-keyword">this</span>.endtime = endtime;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> id;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getNumber</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> number;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setNumber</span><span class="hljs-params">(String number)</span> </span>{
    <span class="hljs-keyword">this</span>.number = number;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Date <span class="hljs-title">getStatTime</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> statTime;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setStatTime</span><span class="hljs-params">(Date statTime)</span> </span>{
    <span class="hljs-keyword">this</span>.statTime = statTime;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Date <span class="hljs-title">getEndtime</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> endtime;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setEndtime</span><span class="hljs-params">(Date endtime)</span> </span>{
    <span class="hljs-keyword">this</span>.endtime = endtime;
}

}

User 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.star.spring.bean;

public class User {
private long id;
private String name;
private int age;

<span class="hljs-comment">// 引用另一个对象</span>
<span class="hljs-keyword">private</span> IdCard idCard;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">()</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id, String name, <span class="hljs-keyword">int</span> age)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
    <span class="hljs-keyword">this</span>.name = name;
    <span class="hljs-keyword">this</span>.age = age;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{<span class="hljs-keyword">return</span> id;}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id)</span> </span>{<span class="hljs-keyword">this</span>.id = id;}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{<span class="hljs-keyword">return</span> name;}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{<span class="hljs-keyword">this</span>.name = name;}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{<span class="hljs-keyword">return</span> age;}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{<span class="hljs-keyword">this</span>.age = age;}

<span class="hljs-comment">// getter</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> IdCard <span class="hljs-title">getIdCard</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> idCard;
}

<span class="hljs-comment">// setter</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setIdCard</span><span class="hljs-params">(IdCard idCard)</span> </span>{
    <span class="hljs-keyword">this</span>.idCard = idCard;
}

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"User{"</span> +
            <span class="hljs-string">"id="</span> + id +
            <span class="hljs-string">", name='"</span> + name + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">", age="</span> + age +
            <span class="hljs-string">", idCard="</span> + idCard +
            <span class="hljs-string">'}'</span>;
}

}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!-- User 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">p:name</span>=<span class="hljs-value">"王五"</span> <span class="hljs-attribute">p:age</span>=<span class="hljs-value">"20"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"idCard"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- IdCard 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.IdCard"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span>></span>
    <span class="hljs-comment"><!-- 使用 <null> 赋空值 --></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"number"</span>></span><span class="hljs-tag"><<span class="hljs-title">null</span>/></span><span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-comment"><!-- 赋值字符串会报错 --></span>
    <span class="hljs-comment"><!--<property name="statTime" value="2222-02-12"/>--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statTime"</span>></span>
        <span class="hljs-comment"><!-- 当前日期 --></span>
        <span class="hljs-comment"><!-- 内部 bean 不能在外部任何其他地方 --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.util.Date"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"endtime"</span>></span>
        <span class="hljs-comment"><!-- 使用 日期格式化实体 bean --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">factory-bean</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">factory-method</span>=<span class="hljs-value">"parse"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"2222-01-31"</span> /></span>
        <span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 创建日期格式化实体 bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.text.SimpleDateFormat"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"yyyy-MM-dd"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

获取实体 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.star.spring;

import com.star.spring.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
public static void main(String[] args) {
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    <span class="hljs-comment">// 根据id值获取bean实例对象</span>
    User user = (User) context.getBean(<span class="hljs-string">"user"</span>);
    System.out.println(user);
}

}

输出

User{id=1, name='王五', age=20, idCard=IdCard{id=1, number='null', statTime=Wed Oct 13 12:46:11 CST 2021, endtime=Thu Jan 31 00:00:00 CST 2222}}

集合属性

在 Spring 中可以通过一组内置的 XML 标签来配置集合属性,例如:

  • 通过指定简单的常量值
  • 通过指定对其他 Bean 的引用。
  • 通过指定内置 bean 定义。
  • 通过指定空元素。
  • 甚至可以内嵌其他集合。

标签有3种属性:

  • :查找全局中的bean。即可以查找其他xml配置文件的bean,优先从当前配置文件寻找
  • :查找当前配置文件中bean,等同于ref属性。local属性值必须同目标beanid属性值相同
  • :指定其依赖的父JavaBean定义

如果有如下实体 bean 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.star.spring.bean;

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

public class Collection {
private String[] array;
private List list;
private Set set;
private Map<String,Integer> map;

<span class="hljs-keyword">public</span> String[] getArray() {
    <span class="hljs-keyword">return</span> array;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setArray</span><span class="hljs-params">(String[] array)</span> </span>{
    <span class="hljs-keyword">this</span>.array = array;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> List<String> <span class="hljs-title">getList</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> list;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setList</span><span class="hljs-params">(List<String> list)</span> </span>{
    <span class="hljs-keyword">this</span>.list = list;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Set<User> <span class="hljs-title">getSet</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> set;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSet</span><span class="hljs-params">(Set<User> set)</span> </span>{
    <span class="hljs-keyword">this</span>.set = set;
}
<span class="hljs-keyword">public</span> Map<String, Integer> getMap() {
    <span class="hljs-keyword">return</span> map;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMap</span><span class="hljs-params">(Map<String, Integer> map)</span> </span>{
    <span class="hljs-keyword">this</span>.map = map;
}

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Collection{"</span> +
            <span class="hljs-string">"array="</span> + Arrays.toString(array) +
            <span class="hljs-string">", list="</span> + list +
            <span class="hljs-string">", set="</span> + set +
            <span class="hljs-string">", map="</span> + map +
            <span class="hljs-string">'}'</span>;
}

}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="hljs-comment"><!-- User 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">p:name</span>=<span class="hljs-value">"王五"</span> <span class="hljs-attribute">p:age</span>=<span class="hljs-value">"20"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"idCard"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- IdCard 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.IdCard"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span>></span>
    <span class="hljs-comment"><!-- 使用 <null> 赋空值 --></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"number"</span>></span><span class="hljs-tag"><<span class="hljs-title">null</span>/></span><span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-comment"><!-- 赋值字符串会报错 --></span>
    <span class="hljs-comment"><!--<property name="statTime" value="2222-02-12"/>--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statTime"</span>></span>
        <span class="hljs-comment"><!-- 当前日期 --></span>
        <span class="hljs-comment"><!-- 内部 bean 不能在外部任何其他地方 --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.util.Date"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"endtime"</span>></span>
        <span class="hljs-comment"><!-- 使用 日期格式化实体 bean --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">factory-bean</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">factory-method</span>=<span class="hljs-value">"parse"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"2222-01-31"</span> /></span>
        <span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 创建日期格式化实体 bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.text.SimpleDateFormat"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"yyyy-MM-dd"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 集合属性 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"collection"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.Collection"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"array"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">array</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>篮球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>足球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">array</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"list"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">list</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13254685465<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13564865487<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">list</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"set"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">set</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
            <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
        <span class="hljs-tag"></<span class="hljs-title">set</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"map"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">map</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">entry</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"key"</span> <span class="hljs-attribute">value-ref</span>=<span class="hljs-value">"user"</span>/></span>
        <span class="hljs-tag"></<span class="hljs-title">map</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

</beans>

使用

1
2
3
4
5
6
7
8
9
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

// 根据 id 值获取 bean 实例对象
User user = (User) context.getBean("user");
System.out.println(user);
// 根据 类型 获取 bean 实例对象
Collection collection = context.getBean(Collection.class);
System.out.println(collection);

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
User{id=1, name='王五', age=20, 
	idCard=IdCard{
		id=1, number='null', statTime=Wed Oct 13 13:50:17 CST 2021, endtime=Thu Jan 31 00:00:00 CST 2222}
	}

Collection{
array=[篮球, 足球],
list=[13254685465, 13564865487],
set=[
User{id=1, name='王五', age=20,
idCard=IdCard{
id=1, number='null', statTime=Wed Oct 13 13:50:17 CST 2021,
endtime=Thu Jan 31 00:00:00 CST 2222
}
}
],
map={
key=User{id=1, name='王五', age=20,
idCard=IdCard{
id=1, number='null', statTime=Wed Oct 13 13:50:17 CST 2021,
endtime=Thu Jan 31 00:00:00 CST 2222
}
}
}
}

util 名称空间

util 命名空间 常用命令

  • util:constant引用某个类型的public static域,并将其暴露为
  • bean util:list 创建一个java.util.List类型的bean,其中包含值或引用
  • util:map 创建一个java.util.Map类型的bean,其中包含值或引用
  • util:properties 创建一个java.util.Properties类型的bean
  • util:property-path 引用一个bean的属性(或内嵌属性),并将其暴露为bean
  • util:set 创建一个java.util.Set类型的bean,其中包含值或引用

并且添加命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       -- 添加 util 名称空间 -->
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
		
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd">
...
beans>

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd"</span>></span>

<span class="hljs-comment"><!-- User 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">p:name</span>=<span class="hljs-value">"王五"</span> <span class="hljs-attribute">p:age</span>=<span class="hljs-value">"20"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"idCard"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- IdCard 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.IdCard"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span>></span>
    <span class="hljs-comment"><!-- 使用 <null> 赋空值 --></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"number"</span>></span><span class="hljs-tag"><<span class="hljs-title">null</span>/></span><span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-comment"><!-- 赋值字符串会报错 --></span>
    <span class="hljs-comment"><!--<property name="statTime" value="2222-02-12"/>--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statTime"</span>></span>
        <span class="hljs-comment"><!-- 当前日期 --></span>
        <span class="hljs-comment"><!-- 内部 bean 不能在外部任何其他地方 --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.util.Date"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"endtime"</span>></span>
        <span class="hljs-comment"><!-- 使用 日期格式化实体 bean --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">factory-bean</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">factory-method</span>=<span class="hljs-value">"parse"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"2222-01-31"</span> /></span>
        <span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 创建日期格式化实体 bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.text.SimpleDateFormat"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"yyyy-MM-dd"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 集合属性 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"collection"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.Collection"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"array"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">array</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>篮球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>足球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">array</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"list"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"list"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"set"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"set"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"map"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"map"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-tag"><<span class="hljs-title">util:list</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"list"</span> <span class="hljs-attribute">list-class</span>=<span class="hljs-value">"java.util.ArrayList"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13254685465<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13564865487<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">util:list</span>></span>
<span class="hljs-tag"><<span class="hljs-title">util:set</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"set"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">util:set</span>></span>
<span class="hljs-tag"><<span class="hljs-title">util:map</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"map"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">entry</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"key"</span> <span class="hljs-attribute">value-ref</span>=<span class="hljs-value">"user"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">util:map</span>></span>

</beans>

bean 继承

Spring 允许继承 bean 的配置,被继承的 bean 称为父 bean。

继承这个父 bean 的 bean 称为子 bean 。

子 bean 从父 bean 中继承配置,包括 bean 的属性配置 。

子 bean 也可以覆盖从父 bean 继承过来的配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.star.spring.bean;

public class Child extends User{
private String child;

<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getChild</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> child;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setChild</span><span class="hljs-params">(String child)</span> </span>{
    <span class="hljs-keyword">this</span>.child = child;
}

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Child{"</span> +
            <span class="hljs-string">"child='"</span> + child + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">"} "</span> + <span class="hljs-keyword">super</span>.toString();
}

}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd"</span>></span>

<span class="hljs-comment"><!-- User 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.User"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span> <span class="hljs-attribute">p:name</span>=<span class="hljs-value">"王五"</span> <span class="hljs-attribute">p:age</span>=<span class="hljs-value">"20"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"idCard"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- IdCard 类实体bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"idCard"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.IdCard"</span> <span class="hljs-attribute">p:id</span>=<span class="hljs-value">"1"</span>></span>
    <span class="hljs-comment"><!-- 使用 <null> 赋空值 --></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"number"</span>></span><span class="hljs-tag"><<span class="hljs-title">null</span>/></span><span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-comment"><!-- 赋值字符串会报错 --></span>
    <span class="hljs-comment"><!--<property name="statTime" value="2222-02-12"/>--></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statTime"</span>></span>
        <span class="hljs-comment"><!-- 当前日期 --></span>
        <span class="hljs-comment"><!-- 内部 bean 不能在外部任何其他地方 --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.util.Date"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"endtime"</span>></span>
        <span class="hljs-comment"><!-- 使用 日期格式化实体 bean --></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">factory-bean</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">factory-method</span>=<span class="hljs-value">"parse"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"2222-01-31"</span> /></span>
        <span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 创建日期格式化实体 bean --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"simpleDateFormat"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"java.text.SimpleDateFormat"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">constructor-arg</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"yyyy-MM-dd"</span> /></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-comment"><!-- 集合属性 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"collection"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.Collection"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"array"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">array</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>篮球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>足球<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">array</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"list"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"list"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"set"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"set"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"map"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"map"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>

<span class="hljs-tag"><<span class="hljs-title">util:list</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"list"</span> <span class="hljs-attribute">list-class</span>=<span class="hljs-value">"java.util.ArrayList"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13254685465<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">value</span>></span>13564865487<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">util:list</span>></span>
<span class="hljs-tag"><<span class="hljs-title">util:set</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"set"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">ref</span> <span class="hljs-attribute">bean</span>=<span class="hljs-value">"user"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">util:set</span>></span>
<span class="hljs-tag"><<span class="hljs-title">util:map</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"map"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">entry</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"key"</span> <span class="hljs-attribute">value-ref</span>=<span class="hljs-value">"user"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">util:map</span>></span>

<span class="hljs-comment"><!-- Child 继承 User --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"child"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"user"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.Child"</span>/></span>

</beans>

使用

1
2
3
4
5
6
// 方式1:在项目中类路径中 resources 下查找xml文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

// 根据 类型 获取 bean 实例对象
Child child = context.getBean(Child.class);
System.out.println(child);

输出结果

1
2
3
4
5
6
7
8
Child{child='null'} 
	User{
		id=1, name='王五', age=20, 
		idCard=IdCard{
			id=1, number='null', statTime=Wed Oct 13 14:50:34 CST 2021, 
			endtime=Thu Jan 31 00:00:00 CST 2222
		}
	}

抽象 bean

父 bean 可以作为配置模板,也可以作为 bean 实例。

若只想把父 bean 作为模板,可以 设置的 abstract 属性为 true,这样 Spring 将不会实例化这个 bean。

如果一个 bean 的 class 属性没有指定,则必须是抽象 bean 。

也可以忽略父 bean 的 class 属性,让子 bean 指定自己的类,而共享相同的属性配置。 但 此时 abstract 必须设为 true。

并不是元素里的所有属性都会被继承。比如:autowire,abstract 等。

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.star.spring.bean;

public class Test {
private long id;
private String name;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> id;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(<span class="hljs-keyword">long</span> id)</span> </span>{
    <span class="hljs-keyword">this</span>.id = id;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
    <span class="hljs-keyword">this</span>.name = name;
}

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Test{"</span> +
            <span class="hljs-string">"id="</span> + id +
            <span class="hljs-string">", name='"</span> + name + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">'}'</span>;
}

}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd"</span>></span>

<span class="hljs-comment"><!-- Test 类 的抽象父类--></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"testParent"</span> <span class="hljs-attribute">abstract</span>=<span class="hljs-value">"true"</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"id"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"1"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"name"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"名称"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
<span class="hljs-comment"><!-- Test 类 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"test"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"testParent"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.star.spring.bean.Test"</span>/></span>

</beans>

输出结果

Test{id=1, name='名称'}

bean 之间依赖

有的时候创建一个 bean 的时候需要保证另外一个 bean 也被创建,这时我们称前面的bean 对后面的 bean 有依赖。

例如:要求创建 Employee 对象的时候必须创建 Department。

这里需要注意的是依赖关系不等于引用关系,Employee 即使依赖 Department 也可以不 引用它。

1
2
3
<bean id="emp03" class="com.star.spring.bean.Employee" depends-on="dept">
	...
bean>

JAVA 代码装配 bean

通过 JavaConfig 在代码中显式配置 Spring Bean。这样就可以不需要使用 xml 配置文件。

@Configuration@bean

创建JavaConfig类的关键在于为其添加@Configuration注解,@Configuration注解表明这个类是一个配置类。

只需要在 @Configuration 注解对应的类中 使用 @bean 注解就可以简单创建吧 bean 实例

添加 @Configuration注解的类会被 Spring 自动扫描加载,并创建对应的 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.star.spring.config;

import com.star.spring.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
// bean的ID与带有@Bean注解的方法名一样
@Bean
public User user() {
return new User();
}

<span class="hljs-comment">// bean的ID=user</span>
<span class="hljs-annotation">@Bean</span>(<span class="hljs-string">"user2"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">user2</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-number">1</span>L,<span class="hljs-string">"张三"</span>,<span class="hljs-number">20</span>)</span></span>;
}

}

这样就配置了两个 bean

@Primary

当一个类有多单例模式个 bean 的时候,可以使用 @Primary 来申明一个默认优先匹配的 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class BeanConfig {
<span class="hljs-annotation">@Bean</span>
<span class="hljs-comment">// 如果有多个则优先匹配这个</span>
<span class="hljs-annotation">@Primary</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> App <span class="hljs-title">app1</span><span class="hljs-params">()</span> </span>{ ... }

<span class="hljs-annotation">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> App <span class="hljs-title">app2</span><span class="hljs-params">()</span> </span>{ ... }

<span class="hljs-comment">// ...</span>

}

@Import

如果配置文件比较多,可以使用 @Import 注解来导入其他的配置文件,这样就可以只引入一个文件,而不用一个一个的引入

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.star.spring;

import com.star.spring.bean.User;
import com.star.spring.config.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({BeanConfig.class})
public class App {
public static void main(String[] args) {
// 使用 AnnotationConfigApplicationContext 加载指定的类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);

    User user = context.getBean(<span class="hljs-string">"user"</span>, User.class);
    System.out.println(user);

    User user2 = context.getBean(<span class="hljs-string">"user2"</span>, User.class);
    System.out.println(user2);
}

}

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.star.spring;

import com.star.spring.bean.User;
import com.star.spring.config.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({BeanConfig.class})
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 单独注册新的 bean
context.register(BeanConfig.class, App.class);
// 需要刷新
context.refresh();

    User user = context.getBean(<span class="hljs-string">"user"</span>, User.class);
    System.out.println(user);

    User user2 = context.getBean(<span class="hljs-string">"user2"</span>, User.class);
    System.out.println(user2);
}

}

输出结果

1
2
User{id=0, name='null', age=0, idCard=null}
User{id=1, name='张三', age=20, idCard=null}

init-methoddestroy-method

@Bean注解支持指定任意的初始化和销毁回调方法,使用 init-method 属性和 destroy-method 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.star.spring.bean;

public class User {
...
public void init() {
// Bean 初始化操作
}
...
public void cleanup() {
// Bean 销毁操作
}
...
}

在配置类中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Configuration
public class BeanConfig {
    // bean的ID与带有@Bean注解的方法名一样
    @Bean(initMethod = "init")
    public User user() {
        return new User();
    }
<span class="hljs-comment">// bean的ID=user</span>
<span class="hljs-annotation">@Bean</span>(<span class="hljs-string">"user2"</span>,initMethod = <span class="hljs-string">"cleanup"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">user2</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-number">1</span>L,<span class="hljs-string">"张三"</span>,<span class="hljs-number">20</span>)</span></span>;
}

<span class="hljs-comment">// 初始化方法也可以不配置,在函数中直接调用是一样的效果</span>
<span class="hljs-annotation">@Bean</span>(<span class="hljs-string">"user2"</span> <span class="hljs-comment">/* ,initMethod = "cleanup" */</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">user2</span><span class="hljs-params">()</span> </span>{
    User user = <span class="hljs-keyword">new</span> User(<span class="hljs-number">1</span>L,<span class="hljs-string">"张三"</span>,<span class="hljs-number">20</span>);
    user.init
    <span class="hljs-keyword">return</span> user;
}

<span class="hljs-comment">// 定义多个名字</span>
<span class="hljs-annotation">@Bean</span>(name={<span class="hljs-string">"userX"</span>,<span class="hljs-string">"userY"</span>})
<span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">user3</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-number">1</span>L,<span class="hljs-string">"张三"</span>,<span class="hljs-number">20</span>)</span></span>;
}

}

@Scope

Spring 包含@Scope注释,以便可以指定 bean 的范围。默认范围是singleton,但可以使用@Scope注释覆盖它

1
2
3
4
5
6
7
8
9
@Configuration
public class MyConfiguration {
    @Bean
    // 可选项:singleton | prototype | request | session | application | websocket
    @Scope("prototype")
    public Xxx xxx() {
        // ...
    }
}

@Description

有时,提供 bean 的更详细的文本描述会很有帮助。可以使用 @Description 来给 Bean 添加描述信息

1
2
3
4
5
6
7
8
@Configuration
public class MyConfiguration {
    @Bean
    @Description("给 Bean 添加描述信息")
    public Xxx xxx() {
        // ...
    }
}

@ImportResource

当需要读取配置文件的时候,可以使用 @ImportResource 注释加载 xml 配置文件。比如说加载 jdbc 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
@ImportResource("classpath:/com/acme/jdbc.xml")
public class AppConfig {
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.url}"</span>)
<span class="hljs-keyword">private</span> String url;

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.username}"</span>)
<span class="hljs-keyword">private</span> String username;

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.password}"</span>)
<span class="hljs-keyword">private</span> String password;

<span class="hljs-annotation">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> DataSource <span class="hljs-title">dataSource</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title">DriverManagerDataSource</span><span class="hljs-params">(url, username, password)</span></span>;
}

}

jdbc.xml 文件

1
2
3
4
5
6
7
8
9
10
11
12

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       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
    https://www.springframework.org/schema/context/spring-context.xsd"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">context:property-placeholder</span> <span class="hljs-attribute">location</span>=<span class="hljs-value">"classpath:jdbc.properties"</span>/></span>

</beans>

jdbc.properties 文件

1
2
3
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb 
jdbc.username=sa 
jdbc.password=

使用

1
2
3
4
5
6
7
8
9
10
@Configuration
@Import({BeanConfig.class,JdbcConfig.class})
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
    JdbcConfig jdbcConfig = context.getBean(JdbcConfig.class);
    System.out.println(jdbcConfig);
}

}

输出结果

JdbcConfig{url='jdbc:hsqldb:hsql://localhost/xdb ', username='sa ', password=''}

@PropertySource

当需要读取配置文件的时候,可以使用 @ImportResource 注释加载 properties 配置文件。比如说加载 jdbc 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.star.spring.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.url:''}"</span>)
<span class="hljs-keyword">private</span> String url;

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.username:''}"</span>)
<span class="hljs-keyword">private</span> String username;

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${jdbc.password:''}"</span>)
<span class="hljs-keyword">private</span> String password;

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"JdbcConfig{"</span> +
            <span class="hljs-string">"url='"</span> + url + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">", username='"</span> + username + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">", password='"</span> + password + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">'}'</span>;
}

}

jdbc.properties 文件

1
2
3
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb 
jdbc.username=sa 
jdbc.password=

使用

1
2
3
4
5
6
7
8
9
10
@Configuration
@Import({BeanConfig.class,JdbcConfig.class})
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
    JdbcConfig jdbcConfig = context.getBean(JdbcConfig.class);
    System.out.println(jdbcConfig);
}

}

输出结果

JdbcConfig{url='jdbc:hsqldb:hsql://localhost/xdb ', username='sa ', password=''}

classpathclasspath\*区别

  • classpath:只会到你的class路径中查找找文件。
  • classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。

查找方法注入

如果 singleton 作用域的 bean 依赖于 prototype 作用域的 bean 的情况下。需要嵌套创建 bean。如:

1
2
3
4
5
6
7
8
9
10
11
public abstract class CommandManager {
    public Object process(Object commandState) {
        // 每次调用该方法都 调用 createCommand() 创建一个 Command 对象
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }
<span class="hljs-comment">// 抽象方法,并且没有实现,正常情况是不能直接使用的</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> Command <span class="hljs-title">createCommand</span><span class="hljs-params">()</span></span>;

}

这种复杂的情况下如何创建 bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Bean
// 注入 多实例 作用域的 bean
@Scope("prototype")
public Command command()
    Command command = new Command();
    return command;
}

@Bean
public CommandManager commandManager() {
// 创建抽象类的对象,并且实现抽象方法
return new CommandManager() {
protected Command createCommand() {
// 在抽象方法中使用
return command();
}
}
}

自动化装配 bean

Spring从两个步骤来实现自动化装配:

  1. 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
  2. 自动装配(autowiring):Spring自动满足bean之间的依赖。

可以使用 xml 配置文件来配置自动扫描 。这样就可以自动扫描 xxx 目录下的所有组件

1
2
3
4
5
6
7
8
9
10
11

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       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
        https://www.springframework.org/schema/context/spring-context.xsd">
	
    <context:component-scan base-package="com.star.spring"/>
beans>

然后使用 ClassPathXmlApplicationContext 来加载

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

也可以在类中使用 @ComponentScan 注解来实现自动扫描组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.star.spring;

import com.star.spring.config.JdbcConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

// 扫描 com.star.spring 包以及子包的所有内容
@ComponentScan({"com.star.spring"})
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);

    JdbcConfig jdbcConfig = context.getBean(JdbcConfig.class);
    System.out.println(jdbcConfig);
}

}

自动扫描过滤器

Spring 提供多种实现过滤器的方式

过滤器类型 示例表达式 描述
annotation (默认) org.example.SomeAnnotation 类级别的注解
的assignable org.example.SomeClass 指定具体的(扩展或实现)的类(或接口)。
aspectj org.example..*Service+ 匹配的 AspectJ 类型表达式。
regex org\.example\.Default.* 正则表达式。
custom org.example.MyTypeFilter org.springframework.core.type.TypeFilter接口的自定义实现。

如:

java 模式

1
2
3
4
5
6
7
@Configuration
@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))
public class AppConfig {
    // ...
}

xml 配置模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       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
        https://www.springframework.org/schema/context/spring-context.xsd">
<span class="hljs-tag"><<span class="hljs-title">context:component-scan</span> <span class="hljs-attribute">base-package</span>=<span class="hljs-value">"org.example"</span>></span>
    <span class="hljs-comment"><!-- 正则匹配 --></span>
    <span class="hljs-tag"><<span class="hljs-title">context:include-filter</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"regex"</span> <span class="hljs-attribute">expression</span>=<span class="hljs-value">".*Stub.*Repository"</span>/></span>
    <span class="hljs-comment"><!-- 排除所有的 @Repository 注解的 --></span>
    <span class="hljs-tag"><<span class="hljs-title">context:exclude-filter</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"annotation"</span> <span class="hljs-attribute">expression</span>=<span class="hljs-value">"org.springframework.stereotype.Repository"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">context:component-scan</span>></span>

</beans>

自动装配模式

Spring 中有多重自动装配方式

模式 描述
no 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的*自动装配*的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的*自动装配*的属性设置为 byType。然后如果它的**类型**匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
autodetect Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。

可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。

组件

@Component是任何 Spring 管理的组件的通用注解。为了使用更具语义化又有很多子组件@Repository@Service@Controller@Configuration 等。如:

1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 继承 Component
public @interface Service {
    // ...
}

所有的组件都会被自动装载,并创建对应的 bean。

@Required

@Required注解适用于 bean 属性 setter 属性注入模式。

从Spring Framework 5.1 开始,@Required注解 和RequiredAnnotationBeanPostProcessor正式弃用。

1
2
3
4
5
6
7
8
9
10
11
public class SimpleMovieLister {
<span class="hljs-keyword">private</span> MovieFinder movieFinder;

<span class="hljs-comment">// setter 模式的注入方式</span>
<span class="hljs-annotation">@Required</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMovieFinder</span><span class="hljs-params">(MovieFinder movieFinder)</span> </span>{
    <span class="hljs-keyword">this</span>.movieFinder = movieFinder;
}
<span class="hljs-comment">// ...</span>

}

@Autowired

@Autowired 注解可以作用在**构造器**、**方法**、**属性**上。使用@Autowired的时候Spring会自动搜索合适的Bean填充到对应的位置。如果没有找到任何适合的Bean就会报错。

@Autowired 默认按byType 匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MovieRecommender {
<span class="hljs-annotation">@Autowired</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserDao userDao;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> RoleDao roleDao;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> CustomerPreferenceDao customerPreferenceDao;

<span class="hljs-annotation">@Autowired</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MovieRecommender</span><span class="hljs-params">(CustomerPreferenceDao customerPreferenceDao)</span> </span>{
    <span class="hljs-keyword">this</span>.customerPreferenceDao = customerPreferenceDao;
}

<span class="hljs-annotation">@Autowired</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setRoleDao</span><span class="hljs-params">(RoleDao roleDao)</span></span>{
    <span class="hljs-keyword">this</span>.roleDao = roleDao
}
<span class="hljs-comment">// ...</span>

}

可以通过设置 @Autowired(required = false) 表示此 bean 为非必须,不存在不会报错

或者,通过 Java 8 来表达依赖项是非必需性质 java.util.Optional,如:

1
2
3
4
5
6
public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(Optional movieFinder) {
        ...
    }
}

从 Spring Framework 5.0 开始,您还可以使用@Nullable注释来设置

1
2
3
4
5
6
public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}

@Qualifier

当自动注入时有多个候选项的时候,有没有 @Primary 来设置默认优先选项,则可以使用 @Qualifier 来指定使用哪一个 bean

1
2
3
4
5
6
7
8
public class MovieRecommender {
<span class="hljs-annotation">@Autowired</span>
<span class="hljs-annotation">@Qualifier</span>(<span class="hljs-string">"main"</span>)
<span class="hljs-keyword">private</span> MovieCatalog movieCatalog;

<span class="hljs-comment">// ...</span>

}

构造函数参数或方法参数上指定注释

1
2
3
4
5
6
7
8
9
10
11
public class MovieRecommender {
<span class="hljs-keyword">private</span> MovieCatalog movieCatalog;

<span class="hljs-annotation">@Autowired</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">prepare</span><span class="hljs-params">(@Qualifier(<span class="hljs-string">"main"</span>)</span> MovieCatalog movieCatalog) </span>{
    <span class="hljs-keyword">this</span>.movieCatalog = movieCatalog;
}

<span class="hljs-comment">// ...</span>

}

@Resource

@Resource 默认通过 byName 自动注入。

所以如果使用name属性,则使用byName的自动注入策略,

而使用type属性时则使用byType自动注入策略。

1
2
3
4
5
6
7
8
public class SimpleMovieLister {
    private MovieFinder movieFinder;
<span class="hljs-annotation">@Resource</span>(name=<span class="hljs-string">"myMovieFinder"</span>) 
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setMovieFinder</span><span class="hljs-params">(MovieFinder movieFinder)</span> </span>{
    <span class="hljs-keyword">this</span>.movieFinder = movieFinder;
}

}

jdk11中移除了 annotation-api 所以需要手动添加

1
2
3
4
5
<dependency>
    <groupId>javax.annotationgroupId>
    <artifactId>javax.annotation-apiartifactId>
    <version>1.3.2version>
dependency>

@Value

@Value 通常用于注入外部配置文件的属性。

如:

配置文件 application.properties

catalog.name=MovieCatalog

配置类

1
2
3
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }

引入配置文件值

1
2
3
4
5
6
7
@Component
public class MovieRecommender {
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${catalog.name}"</span>)
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String catalog;

}

还可以设置默认值

1
2
3
4
5
6
7
@Component
public class MovieRecommender {
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${catalog.name:defaultCatalog}"</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String catalog;

}

@Value 支持使用 SpEL表达式 , 作为自学任务

1
2
3
4
5
6
7
8
9
10
@Component
public class MovieRecommender {
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"#{systemProperties['user.catalog'] + 'Catalog' }"</span>
<span class="hljs-keyword">private</span> String catalog;

<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"#{{'Thriller': 100, 'Comedy': 300}}"</span>)
<span class="hljs-keyword">private</span> Map<String, Integer> countOfMoviesPerCatalog;

}

Spring 提供的内置转换器支持允许自动处理简单的类型转换(toIntegerint)。多个逗号分隔的值可以自动转换为String数组,无需额外的处理。

如:properties类型

app.properties

1
2
array=aaa,bbb,ccc,aaa
maps={key1:"abc","key2":"123"}

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

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

@Configuration
@PropertySource("app.properties")
public class PropertiesConfig {

<span class="hljs-comment">// 映射 数组,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
String[] array1;

<span class="hljs-comment">// 映射 List,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
List<String>[] array2;

<span class="hljs-comment">// 映射 Set,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
Set<String>[] array3;

<span class="hljs-comment">// 映射 Map,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"#{${maps}}"</span>)
Map<String, String> map;

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"PropertiesConfig{"</span> +
            <span class="hljs-string">"array1="</span> + Arrays.toString(array1) +
            <span class="hljs-string">", array2="</span> + Arrays.toString(array2) +
            <span class="hljs-string">", array3="</span> + Arrays.toString(array3) +
            <span class="hljs-string">", map="</span> + map +
            <span class="hljs-string">'}'</span>;
}

}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
package com;

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

@ComponentScan
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
PropertiesConfig bean = context.getBean(PropertiesConfig.class);
System.out.println(bean);
}
}

如:yml类型

app.yml

1
2
3
array: 1,2,3

map: { key1:abc,key2:123 }

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

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

@Configuration
@PropertySource("app.yaml")
public class YamlConfig {

<span class="hljs-comment">// 映射 数组,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
String[] array1;

<span class="hljs-comment">// 映射 List,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
List<String> array2;

<span class="hljs-comment">// 映射 Set,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"${array}"</span>)
Set<String> array3;

<span class="hljs-comment">// 映射 Map,默认字符串</span>
<span class="hljs-annotation">@Value</span>(<span class="hljs-string">"#{${maps}}"</span>)
Map<String, String> map;

<span class="hljs-annotation">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"YamlConfig{"</span> +
            <span class="hljs-string">"array1="</span> + Arrays.toString(array1) +
            <span class="hljs-string">", array2="</span> + array2 +
            <span class="hljs-string">", array3="</span> + array3 +
            <span class="hljs-string">", map="</span> + map +
            <span class="hljs-string">'}'</span>;
}

}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com;

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

@ComponentScan
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);

    YamlConfig bean = context.getBean(YamlConfig.class);
    System.out.println(bean);
}

}

条件装配 bean

在3.1版本中,Spring 引入了bean profile 的功能。如项目分为 dev profile 开发配置或者 prod profile 发布配置,在将应用部署 到每个环境时,要确保对应的 profile 处于激活(active)的状态。

在Java配置中,可以使用 @Profile 注解指定某个bean属于哪一个profile。

@Profile

@Profile 注解可以使用在类和方法上

例如,在配置类中,嵌入式数据库的DataSource可能会配置成如 下所示:

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@Profile("development")
public class StandaloneDataConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }
}

而在部署环境下的时候

1
2
3
4
5
6
7
8
9
@Configuration
@Profile("production")
public class JndiDataConfig {
    @Bean(destroyMethod="")
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

配置文件字符串可能包含一个简单的配置文件名称(例如,production)或配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑(例如,production & us-east)。配置文件表达式支持以下运算符:

  • !:配置文件的逻辑“非”
  • &:配置文件的逻辑“与”
  • |:配置文件的逻辑“或”

但是不能在不使用括号的情况下混合使用&|运算符。

例如: production & us-east | eu-central不是有效的表达式。

它必须表示为 production & (us-east | eu-central)

1
2
3
4
5
6
7
8
9
@Configuration
@Profile("production & (us-east | eu-central)")
public class JndiDataConfig {
    @Bean(destroyMethod="")
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

@ActiveProfiles

接下来可以通过spring.profiles.active属性声明性地激活配置文件,在集成测试中,可以使用 模块中的@ActiveProfiles注释来声明活动配置文件

1
2
3
4
5
@ContextConfiguration
@ActiveProfiles({"dev", "integration"}) 
class DeveloperIntegrationTests {
    // class body...
}

Bean 作用域

Spring Bean 框架支持以下五个作用域,如果使用 web-aware ApplicationContext 时,其中只有三个是可用的。

作用域 描述
singleton 该作用域将 bean 的定义的限制在每一个 Spring IoC 容器中的一个单一实例(默认)。
prototype 该作用域将 bean 的定义限制在任意数量的对象实例。
request 该作用域将 bean 的定义限制为 HTTP 请求。只在 web-aware Spring ApplicationContext 的上下文中有效。
session 该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
global-session 该作用域将 bean 的定义限制为全局 HTTP 会话。只在 web-aware Spring ApplicationContext 的上下文中有效。

singleton 作用域

如果作用域设置为 singleton,那么 bean 是单一实例,并且存储在高速缓存中,针对该 bean 的所有后续的请求和引用都返回缓存对象。

默认作用域是始终是 singleton。

1
2
3
4
5
6
7
8
9
10
package com.star;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

配置文件

1
2
3
4
5
6
7
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-3.0.xsd">

<bean id="helloWorld" class="com.star.HelloWorld" scope="singleton"/>
</beans>

获取

1
2
3
4
5
6
7
8
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
    objA.setMessage("I'm object A");
    objA.getMessage();
    HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
    objB.getMessage();
}

输出结果

1
2
Your Message : I'm object A
Your Message : I'm object A

prototype 作用域

如果作用域设置为 prototype,那么每次特定的 bean 发出请求时 Spring IoC 容器就创建对象的新的 Bean 实例。

1
2
3
4
5
6
7
8
9
10

<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-3.0.xsd"
>

<bean id="helloWorld" class="com.star.HelloWorld" scope="prototype"/>

</beans>

输出结果

1
2
Your Message : I'm object A
Your Message : null

Bean 生命周期

在传统的Java应用中,bean的生命周期很简单。使用Java关键字new进行bean实例化,然后该bean就可以使用了。一旦该bean不再被使用, 则由Java自动进行垃圾回收。

相比之下,Spring容器中的bean的生命周期就显得相对复杂多了。下图展示了bean装载到Spring应用上下文中的一个典型的生命周期过程。

image-20211013151604572

说明:

bean准备就绪之前,bean工厂执行了若干启动步骤:

1.Springbean进行实例化;

2.Spring将值和bean的引用注入到bean对应的属性中;

3.如果bean实现了BeanNameAware接口,Springbean的ID传递给setBeanName()方法;

4.如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;

5.如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的 引用传入进来;

6.如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessBeforeInitialization()方法;

7.如果bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。类似地,如果bean使用initmethod声明了初始化方法,该方法也会被调用;

8.如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization()方法;

9.此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;

10.如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明了销 毁方法,该方法也会被调用。

InitializingBean 初始化接口

org.springframework.beans.factory.InitializingBean 接口为bean提供了afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。

基于代码方式

1
2
3
4
5
public class ExampleBean implements InitializingBean {
   public void afterPropertiesSet() {
      // 初始化任务
   }
}

基于 XML 的方式,可以使用 init-method 属性来指定带有 void 无参数方法的名称。例如:

<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>

下面是类的定义:

1
2
3
4
5
public class ExampleBean {
   public void init() {
      // 初始化任务
   }
}

DisposableBean 销毁回调

org.springframework.beans.factory.DisposableBean 接口为bean提供了 destroy 方法,凡是继承该接口的类,在销毁 bean 的时候都会执行该方法。

基于代码方式:

1
2
3
4
5
public class ExampleBean implements DisposableBean {
   public void destroy() {
      // 销毁任务
   }
}

在基于 XML 的方式,可以使用 destroy-method 属性来指定带有 void 无参数方法的名称。

<bean id="exampleBean" class="examples.ExampleBean" destroy-method="destroy"/>

下面是类的定义:

1
2
3
4
5
public class ExampleBean {
   public void destroy() {
      // 销毁任务
   }
}

默认的初始化和销毁方法

如果有太多具有相同名称的初始化或者销毁方法的 Bean,那么不需要在每一个 bean 上声明**初始化方法**和**销毁方法**。

框架使用 元素中的 default-init-methoddefault-destroy-method 属性提供了灵活地配置这种情况,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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-3.0.xsd"
<!<span class="hljs-attribute">--</span> 默认每个实体类都会执行该实体类的 <span class="hljs-attribute">init</span>、<span class="hljs-attribute">destroy</span>方法 <span class="hljs-attribute">--</span>></span>
default-init-method="init" 
default-destroy-method="destroy">

<bean id="..." class="...">
...
</bean>

</beans>

作业

自动 JDBC

    </article>
posted @ 2021-11-20 16:59  柠檬色的橘猫  阅读(20)  评论(0)    收藏  举报