Spring 概述
Spring 框架是一个轻量级的企业级开发的一站式解决方案。所谓解决方案就是可以基于Spring 解决 Java EE 开发的所有问题。 Spring 框架主要提供了 IoC 容器、 AOP 、数据访问、 Web开发、消息、测试等相关技术的支持。
Spring 使用简单的 POJO (Plain Old Java Object,即无任何限制的普通Java 对象〉来进行企业级开发。每一个被 Spring 管理的 Java 对象都称之Bean;而 Spring 提供了一个 IoC 容器用来初始化对象,解决对象间的依赖管理和对象的使用。
1.Spring 的发展过程
1.1 Spring 1.x 时代
在Spring1.x时代,都是通过xml文件配置bean,随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和xml配置文件中切换。
1.2 Spring 2.X时代
随着JDK 1.5带来的注解支持,Spring2.x可以使用注解对Bean进行申明和注入,大大的减少了xml配置文件,同时也大大简化了项目的开发。
那么,问题来了,究竟是应该使用xml还是注解呢?
最佳实践:
1、 应用的基本配置用xml,比如:数据源、资源文件等;
2、 业务开发用注解,比如:Service中注入bean等;
1.3 Spring3.x到Spring4.x
java配置是Spring4.x推荐的配置方式,可以完全替代xml配置。
1.4 Spring的Java配置
Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置。
1.5 @Configuration和@Bean
Spring的Java配置方式是通过 @Configuration 和 @Bean 这两个注解实现的:
1、@Configuration 作用于类上,相当于一个xml配置文件;
2、@Bean 作用于方法上,相当于xml配置中的 < bean >;
2. Spring能做什么
官网解释:
3. Spring 项目快速搭建
方法一:在https://start.spring.io/创建Spring项目,并下载到本地,导入IDEA中
在IDEA中打开目录结构和Maven的目录结构一致。
方法二:在IDEA中创建一个Maven 项目,在pom.xml文件中添加相应依赖
4.Spring的模块
Spring是模块化的,这意味着开发者可以只使用需要的Spring模块
(1)核心容器( Core Container)
- Spring-Core :核心工具类, Spring 其他模块大:留;使用 Spring-Core;
- Spring-Beans: Spring 定义 Bean 的文持:
- Spring-Context :运行时 Spring 容器:
- Spring-Context-Support: Spring 容器对第二方包的集成支持:
- Spring” Expression :使用表达式语言在运行时查询和操作对象。
(2) AOP
- Spring-AOP:基于代理的 AOP 支持:
- Spring-Aspects :基于 AspectJ 的 AOP 支持。
(3)消息( Messaging)
- Spring”Messaging :对消息架构和协议的支持。
** (4) Web**
- Spring-Web:提供基础的 Web 集成的功能,在 Web 项目中提供 Spring 的容器:
- Spring-Webmvc:提供基于 Servlet 的 Spring MVC;
- Spring-WebSocket:提供 WebSocket 功能:
- Spring-Webmvc-Portlet:提供 Portlet 环境支持。
(5)据访问/集成( Data Access/Integration)
- Spring-JDBC :提供以 JDBC 访问数据库的支持:
- Spring-TX:提供编程式和声明式的事务支持:
- Spring-ORM:提供对对象/关系映射技术的支持:
- Spring-OXM :提供对对象/xml 映射技术的支持:
- Spring-JMS :提供对 JMS的支持。
5. Spring的生态
Spring 发展到现在已经不仅仅是 Spring 框架本身的内容, Spring 目前提供了大量的基于Spring 的项目,可以用来更深入地降低我们的开发难度,提高开发效率。
目前 Spring 的生态里主要有以下项目,我们可以根据自己项目的需要来选择使用相应的项目。
- Spring Boot:使用默认开发配置来实现快速开发。
- Spring XD:用来简化大数据应用开发。
- SpringCloud:为分布式系统开发提供工具集。
- Spring Data:对主流的关系型和 NoSQL 数据库的支持。
- Spring Integration:通过消息机制对企业集成模式 CEIP )的支持。
- Spring Batch:简化及优化大量数据的批处理操作。
- Spring Security:通过认证和授权保护应用。
- Spring HATEOAS :基于 HATEOAS 原则简化 REST服务开发。
- Spring Social :与社交网络 API (如 Facebook、新浪微博等)的集成。
- SpringAMQP :对基于 AMQP 的消息的支持。
- Spring Mobile:提供对手机设备检测的功能,给不同的设备返回不同的页面的支持。
- Spring for Android:主要提供在 Android 上消费 RESTfulAPI 的功能。
- Spring Web Flow:基于 SpringMVC 提供基于向导流程式的 Web 应用开发。
- Spring Web Services:提供了基于协议有限的 SOAP/Web 服务。
- Spring LDAP :简化使用 LDAP 开发。
- Spring Session:提供一个 API 及实现来管理用户会话信息。
6.Spring 基础配置
Spring框架本身有四大原则:
- 1)使用POJO进行轻量级和最小侵入式开发
- 2)通过依赖注入和基于接口编程实现松耦合
- 3)通过AOP和默认习惯进行声明式编写
- 4)使用AOP和模板(template)减少模式化代码
Spring所有功能的设计和实现都是基于此四大原则的。
6.1 依赖注入(dependency injection 即DI)
6.1.1 DI的概念
所谓依赖注入指的就是容器负责创建对象和维护对象间的依赖关系,而不是通过对象本身负责自己的创建和依赖。
6.1.2 为什么需要DI
依赖注入的主要目的是为了解耦,体现了一种“组合”的理念。如果你希望你的类具备某项功能的时候,是继承自一个具有此功能的父类好呢?还是组合另外一个具有这个功能的类好呢?答案是不言而喻的,继承一个父类,子类将与父类耦合,组合另外一个类则使耦合度大大降低。
- Spring loC容器( ApplicationContext)负责创建Bean,并通过容器将功能类Bean注入到你需要的Bean中。Spring 提供使用xml、注解、Java配置实现Bean的创建和注 入。
- 无论是xml配置、注解配置还是Java配置,都被称为配置元数据,所谓元数据即描述数据的数据。元数据本身不具备任何可执行的能力,只能通过外界代码来对这些元数据行解析后进行一些有意义操作。Spring容器解析这些配置元数据进行Bean初始化、配置和管理依赖。
6.1.3 声明Bean的注解
@Component组件,没有明确的角色
@Service 在业务逻辑层使用(Dao层)
@Repository 在数据访问层使用(Service层)
@Controller 在展示层使用(MVC)
注入Bean的注解,一般使用:
@Autowired 可以注解在set方法上或者属性上
6.1.4 举个例子
类A的定义如下:
package com.example.yuisma;
import org.springframework.stereotype.Service;
/**
* @ClassName A
* @Description 编写功能类的Bean
* @Author yuisama
* @Date 2020/4/30 14:50
*/
//使用@Service注解声明当前类是Spring管理的一个Bean
//也可以使用其他注解@Compoent @Repository @Controller,根据需要使用
@Service
public class A {
public String sayHello(String word){
return "hello world !";
}
}
类B的定义如下
package com.example.yuisma;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName B
* @Description 编写一个类B,将类A注入到类B中
* @Author yuisama
* @Date 2020/4/30 14:55
*/
//@Service注解声明当前类是Spring管理的一个Bean
@Service
public class B {
//用@Autowired注解将类A的实体Bean注入到当前类B中
//让当前这个类具备类A的功能
@Autowired
A a;
public String sayHello(String word){
//当前这个类已经拥有类A的功能,可以直接调用其中的方法
return a.sayHello(word);
}
}
编写一个配置类
package com.example.yuisma;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName ConfDemo
* @Description 这是一个配置类
* @Author yuisama
* @Date 2020/4/30 15:00
*/
//声明当前类是一个配置类
@Configuration
//@ComponentScan表示自动扫描这个包路径下所有使用@Service @Compenent @Repository @Controller的类,并注册为Bean
@ComponentScan("com.example.yuisma")
public class ConfDemo {
}
主函数如下
package com.example.yuisma;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class YuismaApplication {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext 作为Spring 容器,接受输入一个配置类作为
//参数;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ConfDemo.class);
B b = context.getBean(B.class);
System.out.println(b.sayHello("di"));
context.close();
}
}
运行结果
6.2 Java配置
Java 配置是Spring 4.x 推荐的配置方式,可以完全替代xml 配置: Java 配置也是Spring Boot推荐的配置方式。
Java 配置是通过@Configuration 和@Bean 来实现的。
- @Configuration声明当前类是一个配置类,相当于Spring配置的xml文件
- @Bean注解在方法上,声明当前方法的返回值是一个Bean
示例
我们通过Spring MVC的三层模型来介绍Java配置。首先创建一个实体类User
package com.example.yuisma.JavaBeanDemo;
/**
* @ClassName User
* @Description 实体类
* @Author yuisama
* @Date 2020/4/30 16:07
*/
public class User {
private String userName;
private String passwd;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
编写持久化层代码,模拟与数据库的交互
package com.example.yuisma.JavaBeanDemo;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName UserDao
* @Description 持久化层
* @Author yuisama
* @Date 2020/4/30 16:08
*/
//模拟生成一组数据放在List集合中
@Repository
public class UserDao {
public List<User> queryUser(){
List<User> result = new ArrayList<>();
for (int i = 0; i <10 ; i++) {
User user= new User();
user.setUserName("name "+i);
user.setPasswd("passwd"+i);
result.add(user);
}
return result;
}
}
编写Service层 UserService 用于实现业务逻辑
package com.example.yuisma.JavaBeanDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @ClassName UserService
* @Description Service层
* @Author yuisama
* @Date 2020/4/30 16:11
*/
@Service
public class UserService {
//将UserDao注入到这个类中
@Autowired
private UserDao userDao;
public List<User> queryUser(){
//调用userDao中方法进行查询
return this.userDao.queryUser();
}
}
编写配置类用于实例化Spring容器
package com.example.yuisma.JavaBeanDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName SpringConfig
* @Description TODO
* @Author yuisama
* @Date 2020/4/30 16:23
*/
//这个注解表明这个类是配置类,相当于一个xml文件
@Configuration
@ComponentScan(basePackages = "com.example.yuisma.JavaBeanDemo")
public class SpringConfig {
//这个注解表明这是一个Bean对象,相当于xml中的<bean>
@Bean
public UserDao getUserDao(){
return new UserDao();
}
}
编写测试方法,用于启动Spring容器
package com.example.yuisma.JavaBeanDemo;
import com.example.yuisma.A;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.List;
/**
* @ClassName Test
* @Description TODO
* @Author yuisama
* @Date 2020/4/30 16:27
*/
public class Test {
public static void main(String[] args) {
//通过java配置来实例化容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
//在spring容器中获取Bean对象
UserService userService = context.getBean(UserService.class);
List<User> list = userService.queryUser();
for (User user : list) {
System.out.println(user.getPasswd() + user.getUserName());
}
//销毁该容器
context.destroy();
}
}
执行结果:
从这个示例中可以看出,使用java配置可以代替XML配置。
6.3 AOP(面向切面编程)
在Spring1.x时代,都是通过xml文件配置bean,随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和xml配置文件中切换。
Spring 支持AspectJ 的注解式切面编程。