一、为什么要使用Spring?
Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。
为什么要使用Spring?原因很简单,Spring有很多特点:
轻量: Spring 是轻量的,基本的版本大约2MB。
控制反转: Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
面向切面的编程(AOP): Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
容器: Spring 包含并管理应用中对象的生命周期和配置。
MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
事务管理: Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务
1.1、程序的耦合和解耦合
藕合就是程序间的依赖关系。解藕就是降低程序间的依赖关系。在开发过程中应做到编译期不依赖,运行时再依赖。
解藕思路:
1、使用反射来创建对象,而不使用new关键字
2、通过读取配置文件来获取要创建的对象全限定名
问:以前写的代码有什么问题?
创建java控制台程序
创建Dao类
创建service并调用Dao
创建测试类并调用service
层与层之间的关系通过new来实现调用,并且new对象时需要导入该对象所在的正确的包名,否则报错。这种关系称为耦合关系。
二、IOC
2.1、为什么要使用IOC?
IOC呢,也就是控制反转,它的核心思想就是把对象的管理权交给了容器,那么,应用程序如果需要使用某个对象的实例,就可以直接从IOC容器里获取了。
这种设计的好处就在于降低了程序中对象与对象之间的耦合性,使得程序的整个体系结构变得更加灵活。
2.1、IDEA中使用IOC
第1步:创建一个普通Maven项目
第2步:添加依赖
在pom.xml中添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
</dependencies>
三、切片1:通过xml使用IOC
3.1、注入Java实体
3.1.1、需求定义
使用IOC实现User对象的注入
3.1.2、需求实现
User.java的创建
package practice.entity;
public class User {
private int id;
private String name;
private Date birth;
//Get和Set方法,重写toString方法
}
beans.xml配置文件
按图操作,将beans.xml配置文件设置成一个应用程序的上下文文件
注入User对象的信息
在beans中配置User的信息,设定user的姓名等属性。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="practice.entity.User">
<property name="id" value="1001"></property>
<property name="name" value="二哈"></property>
<!-- 引用日期对象 -->
<property name="birth" ref="date_ref"></property>
</bean>
<!-- 实例化日期对象 -->
<bean id="date_ref" class="java.util.Date"></bean>
</beans>
创建测试类进行测试
package practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import practice.entity.User;
public class Test {
public static void main(String[] args) {
//在配置文件中获取应用程序上下文
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//从ioc容器中获取User对象,并注入到myUser中
User myUser = (User) context.getBean("user");
System.out.println(user.toString());
}
}
四、切片2:通过注解使用IOC
注解配置和 xml配置要实现的功能都是一样的,都是要降低程序间的耦合。只是配置的形式不一样。关于实际的开发中到底使用 xml还是注解,每家公司有着不同的使用习惯。
4.1、知识点讲解
4.1.1、@Component
用于创建对象的注解
相当于:<bean id="" class="">
作用: 把资源让 spring 来管理。相当于在 xml 中配置一个 bean。 属性: value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。
代码演示
User实体类
定义一个User实体类,通过@Component将该类的对象注入到IOC容器
package practice.entity;
import org.springframework.stereotype.Component;
@Component
//@Component("uuu")
public class UserInfo {
public void showUser(){
System.out.println("我叫二哈,今年18岁");
}
}
beans.xml配置类
在配置类中我们通过component-scan注解扫描所有使用注解的类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描注解类 -->
<context:component-scan base-package="practice"/>
</beans>
测试类
package practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import practice.entity.User;
public class Test1 {
public static void main(String[] args) {
//读取Spring的核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
//从IOC容器中获取User对象
User usr = (User) ctx.getBean("userInfo");
usr.showUser();
}
}
4.1.2、@Component衍生的注解
除了上面使用到的Component注解外还有几个常用的注解: @Component: 用于任意类的注入 @Repository: 用于标识在dao类上 @Service: 用于标识在Service类上 @Controller: 用于标识在控制器类上
Ps:使用方式和@Component一样
4.1.3、用于注入数据的注解
相当于:<property name="" ref="">
4.1.3.1、@Autowired
按照Bean的类型,从IOC容器中获取对象进行装配。
代码演示
UserInfo实体类
//@Component("uuu")
//@Component
@Repository
public class UserInfo {
public void showUserInfo(){
System.out.println("我叫二哈,今年18岁");
}
}
UserService
通过@Autowired注解从ioc容器获取UserInfo对象
@Service
//@Scope("singleton") //单例
@Scope("prototype") //多例
public class UserService {
@Autowired
//@Resource
private UserInfo userInfo;
public void showUser(){
System.out.println("哈哈哈,我是userService");
userInfo.showUserInfo();
}
}
beans.xml
在beans.xml中开启注解扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描注解类 -->
<context:component-scan base-package="practice"/>
</beans>
测试类
package practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
//读取Spring的核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
//从IOC容器中获取User对象
UserService userService = (UserService) ctx.getBean("userService");
userService.showUser();
}
}
4.1.4、@ Scope
@ Scope注解:用于指定bean的作用范围,属性value:指定范围的取值。 常用取值:singleton(单例)、 prototype(多例)和生命周期相关,他们的作用就和在bean标签中使用init-method和destroy-methode的作用是一样的
案例:演示单例模式
修改service实现类
修改service实现类
@Service
//@Scope("singleton") //单例
@Scope("prototype") //多例
public class UserService {
// @Autowired
@Resource
private UserInfo userInfo;
public void showUser(){
System.out.println("哈哈哈,我是userService");
userInfo.showUserInfo();
}
}
修改测试类
package demo1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
public static void main(String[] args) {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) cxt.getBean("userService");
userService.showUser();
UserService userService1 = (UserService) cxt.getBean("userService");
System.out.println(userService == userService1);
}
}
五、Spring5的新注解
spring的核心配置文件除了可以用xml之外还可以使用一个java类来代替xml配置文件。如果要使用java类做为核心配置类,需要使用特定的注解,这些注解是在spring 5的版本中新加的
5.1、@Configuration
用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
5.2、@ComponentScan
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的: <context:component-scan base-package="com "/>是一样的 属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样 语法: @ComponentScan(basePackages = {"要扫描的包名1","要扫描的包名2",...})
5.3、综合应用
@Configuration和@ComponentScan的综合应用,零配置文件实现IOC
修改之前切片2的案例
第1步:将beans.xml配置文件删除
第2步:添加配置文件
使用@Configuration注解定义配置类,使用@ComponentScan注解开启注解的自动扫描
package demo2;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"demo2"})
public class SpringConfig {
}
第3步:添加要注入到ioc容器的实体
package demo2;
import org.springframework.stereotype.Component;
@Component
public class UserIntro {
public void showUserInfo(){
System.out.println("我叫二哈,今年18岁");
}
}
第3步:修改测试类
通过AnnotationApplicationContext获取IOC容器。
package demo2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class);
UserIntro intro = (UserIntro) cxt.getBean("userIntro");
intro.showUserInfo();
}
}