Spring框架是什么?
spring安装本人的理解就是一艘航空母舰,其拥有很多不同的作战系统以及武器也可以与其他军事力量组装成一个航母战斗群。对应着我们的spring,其拥有从企业级到云计算等各个方面的技术栈,如下图所示:
Spring拥有很多项目有如:Spring Boot 、Spring Framework、Spring Cloud等等,这里就不在一一介绍,感兴趣的同学们可以去官方网站查询和了解。
Spring框架又是Spring技术栈的核心,Spring框架的IOC与AOP编程方式大大简化了Java企业级开发并极大提高了开发效率,并且Spring框架优秀的低浸入式降低了代码耦合性以及其他优秀的框架的集成,这些都让Spring框架成为一个非常受欢迎的Java开发框架。
Spring框架常用模块
一个经典的Spring模块图如下所示:
- Test
Spring Test通过Junit与TestNG实现集成测试与单元测试。 - Core
核心容器(Core Container)由 Spring Bean、Spring Core、Spring Context、Spring expression四个模块组成。
- Spring Bean 与Spring Core
提供了控制反转(IOC)与依赖注入(DI)管理Java Bean对象,其底层使用的Bean Factory复杂工厂进行实现,使创建的对象与实际程序依赖进行解偶。 - Spring Context
Context继承Bean模块特性,拥有事件传播、上下文创建、资源加载等,其中Spring-Context-Support集成第三方优秀框架,以使它们可以集成Spring的上下文中。 - Spring Expression
是一种强大的表达式,可以用来操作和查询对象图中使用。
- AOP Aspects
Spring Aop提供面向切面编程实现。 - Data Access、Integration
数据访问、集成模块包含JDBC、ORM、OXM、JMS、Transition模块。
- Spring JDBC提供了一套模版,使用其可以很方便操作数据库。
- Spring ORM 为流行的对象关系映射提供API,如JPA与Hibernate。
- Spring JMS 提供了消息集成模块如:生产消息与消费消息等。
- Spring OXM 提供了一个支持对象到XML关系映射的功能。
- Web
此模块由Spring Web 、Spring-Webmvc、Spring-WebSocket、Spring-Portlet等模块组成。
- Spring web 提供了一套面向web开发的集成功能如Servlet容器监听、web应用程序上下文等。
- Spring servlet也称Spring webmvc主要集成了Spring的MVC模块与REST服务等功能。
- Spring webSocket基于webScoket协议开发的应用程序。
IOC
Spring通过IOC容器管理Java Bean对象的创建以及其依赖。软件开发中经常会有写耦合性强的代码,通过Spring IOC可以很好帮我解决这个问题。IOC的核心是DI,通过DI可以设置不同Java Bean组件的依赖项,并在其整个生命周期都能管理这些依赖项。这些原先需要程序亲自创建并管理的工作交给了Spring容器实现,所以称为“控制反转”,IOC实现有两种方式:一是依赖注入,另一种就是依赖查找。
- 配置元数据
使用Spring管理Java Bean对象之前需要我们配置元数据,Spring可以通过XML配置,也可采用注解或者基于Java类的配置,下面将介绍使用XML配置Java Bean的元数据配置和使用。
实例化Bean对象的几种方式
使用无参构造函数实例化对象
这里我们使用Maven构建我们的Spring应用,其依赖POM文件内容如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--引入Spring依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
<build>
<finalName>Spring-FramerWork</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
创建简单类Student如下:
@Data
public class Student {
private String name;
private Integer age;
private String gender;
private String address;
public Student() {
}
public Student(String name, Integer age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
}
Spring元数据配置XML文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student1" class="com.codegeek.day1.Student">
<property name="address" value="上海"/>
<property name="name" value="小明"/>
<property name="age" value="23"/>
<property name="gender" value="男"/>
</bean>
</beans>
上面的XML文件中,Id属性是标记一个bean对象的唯一标志,类似于我们生活中每个人对应的身份证一样,class属性定义Bean的类型也就是类的全路径。property属性对应Java Bean中的属性名称,而value就是对应Bean属性名的值。
新建Spring测试类如下:
public class SpringTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student1 = applicationContext.getBean("student1", Student.class);
System.out.println(student1);
}
}
ApplicationContext是高级工厂接口,能维护不同的Bean及其依赖项。其提供的getBean方法可以获取一个Bean的实例对象。运行结果显示我们确实获得了一个Student对象,而这个对象是由Spring容器为我们创建的。
整个项目结构如下所示:
思考🤔几个问题?
- Student类在容器中何时创建?
当我们对Java对象的构造器代码进行修改如下所示:
- 无参构造器修改
public Student() {
System.out.println("Student.... 空参");
}
- 有参构造器修改
public Student(String name, Integer age, String address) {
System.out.println("Student.... 有参");
this.name = name;
this.age = age;
this.address = address;
}
- 属性方法修改
public void setAddress(String address) {
System.out.println("address 被设置了");
this.address = address;
}
- 测试类修改
运行结果如下:
结论
我们发现我们并没有从容器取Student对象,但是其无参构造器执行一次,然后调用对象的属性setter方法。故可知在容器初始化时Spring就已经为我们创建好了Java Bean对象。
- 容器获取一个不存在的对象会有什么结果?
- 测试类修改
运行测试类后控制台输出如下:
-结论
若尝试在IOC容器中获取不存在的对象容器将会报NoSuchBeanDefinitionException
。
- 根据类类型获取对象需要注意什么?
xml中新增配置如下:
<bean id="student2" class="com.codegeek.day1.Student">
<property name="address" value="上海"/>
<property name="name" value="小红"/>
<property name="age" value="24"/>
<property name="gender" value="女"/>
</bean>
- 测试类代码如下:
运行结果如下所示: - 结论
程序报了No qualifying bean of type 'com.codegeek.day1.Student' available: expected single matching bean but found 2
的异常,根据类型获取Java Bean对象,需要满足Bean对象在IOC容器中具有唯一定义要求。
使用有参构造函数实例化对象
Xml配置元数据如下所示:
测试类如下所示:
运行结果:
当Xml中value属性值类型与有参构造函数参数类型一致时可以省略name属性如下:
运行结果不变,但是这样配置可能出现一些问题,新增Xml元数据配置如下所示:
<bean id="student4" class="com.codegeek.day1.Student">
<constructor-arg value="张三"/>
<constructor-arg value="23"/>
<constructor-arg value="男"/>
<constructor-arg value="北京"/>
</bean>
运行类如下:
运行结果如下所示:
我们发现运行结果属性名对应的属性值明显不符合实际生活逻辑,故xml可以改进如下所示:
再次运行测试类运行结果,一起正常如下所示:
静态工厂方法实例化对象
当采用静态工厂方法创建Bean时,除了指定class类型之外,还需要指定其工厂方法,以便容器初始化调用此方法完成类的初始化。
定义Xml数据如下:
定义实体类如下:
public class InstanceFactory {
public static Phone instance(String brandName, Double price, String producePlace) {
return new Phone(brandName,price,producePlace);
}
public Phone getPhone(String brandName,Double price,String producePlace) {
return new Phone(brandName,price,producePlace);
}
}
使用工厂方法实例化对象
此种配置需设置factory-bean
属性,而此属性的值必须是在IOC容器配置的,Xml配置如下所示:
测试类代码:
以上代码可在 codegeekgao.git 下载查看,下一章将重点学习和了解IOC容器依赖注入方式学习。