一、spring是什么?
spring是开源Java软件框架,利用这套框架可以快速搭建java软件
二、spring框架两个核心功能1.IOC/ID
2.AOP
1.1 IOC
1.主动控制:由应用程序主动控制管理“对象组件”。适合管理创建简单的对象
2.控制反转:由外部容器环境(框架)创建管理“对象组件”交给应用程序使用。适合管理创建过程复杂的对象。从对象使用者的角度看是简单的
1.2 Java Bean
为了规范Java类的定义,Java提供Java Bean规范,所谓的javabean规范就是约定Java类的定义规则,使程序一致,方便使用和交流。其约定如下:
- 需要定义包package
- 有无参的构造器
- 需要实现序列化接口
- 包含使用 getXxx setXxx 声明的“Bean属性” xxx
- a.Bean属性(Bean Property)就是指 setXxx getXxx方法
- b.对象属性(Object Field)是指对象的实例变量
1.3 JUnlt测试Spring
JUnlt提供了@Before和@After注解,这两个注解声明的方法可以在测试案例方法之前和之后执行。
测试spring时候需要spring容器的代码冗长麻烦,利用JUnit的@Before和@After注解声明方法,封装spring的初始化和销毁方法,可以一劳永逸的解决spring的初始化问题
1.4 主键扫描
1.4.1 spring主键扫描
spring提供主键扫描注解,利用组件扫描注解和主键配合,可以自动扫描包空间自动创建Bean对象,减少编码,提高编程效率
1.4.2 spring提供多种组件注解
spring提供了多种注解,用于程序中不同用途的组件标注,这些注解名字不同但是其作用相同,这些包括:
- @Controller,控制器组件
- @Service,业务层组件
- @Component,通用组件
使用组件@Component注解声明类
package cn.tedu.pojo; import org.springframework.stereotype.Component; import java.io.Serializable; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Component //spring 在组件扫描时候会找到标注@Component的类 //将类创建为对象,并且其Bean ID为“DemoBean” public class DemoBean implements Serializable { //实现序列化:防止在进入缓存阶段时,程序出错 @Override public String toString() { return "DemoBean"; } }
在配置类上使用注解扫描功能
package cn.tedu.demo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Configuration //此类为配置文件 @ComponentScan(basePackages = "cn.tedu.pojo") //指定被扫描的包 public class Config { @Bean /** * 告诉spring在启动时候,加载被@#Bean标准的方法 * 返回值是spring创建的对象,方法名是Bean的ID * */ public Demo bean(){ return new Demo(); } }
测试
@Test public void testDemoBean(){ /** 测试组件扫描功能*/ DemoBean bean = ctx.getBean("demoBean", DemoBean.class); System.out.println(bean); }
由于剩下两个组件的使用方式类似,除了名字不同,作用一样,就不一一举例
1.4.3自定义组件ID
在使用组件扫描功能时候@Component注解可以添加属性,自定义组件的ID。定义了自定义组件ID以后,基于可以使用新的ID管理组件,原有的默认组件ID就不再有效。
package cn.tedu.pojo; import org.springframework.stereotype.Controller; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Controller("controller") //定义此ID,则基于此ID管理组件 public class DemoController { @Override public String toString() { return "DemoController"; } }
开发中很少这么设定Bean ID,尽量采用默认规则,这样有助于减少代码,减少错误
1.5 Spring Bean管理
1.5.1 Bean的作用域
spring针对对象的不同作用范围设计看Bean作用域,spring的Bean常用的作用域用两个singeton(单例),prototype(原型):
spring中默认情况下Bean组件作用域是单例,也就是说任何时候调用getBean方法获得的对象都是同一个实例。这么设计优点是一个Bean可以被复用,提高了内存资源利用率,但是也有问题,每个对象状态都是不同的Bean就不合适
案例:
@Test public void testSingleton(){ DemoBean bean1 = ctx.getBean("demoBean", DemoBean.class); DemoBean bean2 = ctx.getBean("demoBean", DemoBean.class); System.out.println(bean1==bean2); System.out.println(bean1.equals(bean2)); }
运行结果:
初始化 true true 19:46:03.576 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@41ee392b, started on Fri Oct 29 19:46:03 CST 2021 销毁
在设置了@Scope("prototype")注解以后,Bean作用域是“原型”,此时是每次调用getBean都会创建一个对象实例
案例:
package cn.tedu.pojo; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Component @Scope("prototype") public class ExampleBean { @Override public String toString() { return "ExampleBean"; } }
测试案例:
@Test public void testPrototype(){ ExampleBean bean1 = ctx.getBean("exampleBean", ExampleBean.class); ExampleBean bean2 = ctx.getBean("exampleBean", ExampleBean.class); System.out.println(bean1==bean2); System.out.println(bean1.equals(bean2)); }
运行结果:初始化 false false 19:51:35.052 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@41ee392b, started on Fri Oct 29 19:51:34 CST 2021 销毁 //运行结果说明两个调用getBean方法得到的两个不同对象引用,也就是创建了多个对象实例
1.5.2 对象生命周期管理
当使用Spring IOC后,Spring IOC提供了对象声明周期管理功能。你可以利用生命周期管理注解,标注到方法上,Spring就会创建对象,销毁对象时候执行相应的方法。这样就可以让Spring帮助管理对象的生命周期,充分利用IOC容器提供的对象生命周期管理功能
Spring提供两种管理对象生命周期的方式:
测试案例1:@PostConstruct @PreDestroy
1.利用Maven导入javax.annotation注解
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.0</version> </dependency>
2.声明Bean组件类型
package cn.tedu.pojo; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.IOException; import java.io.PrintWriter; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 * * 测试第一种管理对象生命周期的方式 * 使用@Component注解管理Bean组件时候,使用 */ @Component public class FileLogger { public PrintWriter out; @PostConstruct public void open() throws IOException { out = new PrintWriter("Demo.txt"); System.out.println("打开文件Demo.txt"); } @PreDestroy public void close(){ out.close(); System.out.println("关闭文件Demo.txt"); } }
3.测试案例:
@Test public void testPostConstruct(){ FileLogger fileLogger = ctx.getBean("fileLogger", FileLogger.class); fileLogger.out.println("Hi"); fileLogger.out.println("Test!"); }
测试结果
打开文件Demo.txt 20:40:10.537 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'logger' 打开文件Demo.txt 20:40:10.557 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean' 初始化 20:40:10.594 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@668bc3d5, started on Fri Oct 29 20:40:10 CST 2021 关闭文件Demo.txt 关闭文件Demo.txt 销毁 Process finished with exit code 0
测试案例2: initMethod destroyMethod
1.编程被测试的类型
package cn.tedu.pojo; import java.io.IOException; import java.io.PrintWriter; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ public class DemoLogger { public PrintWriter out; public void open() throws IOException { out = new PrintWriter("Demo.txt"); System.out.println("打开文件Demo.txt"); } public void close(){ out.close(); System.out.println("关闭文件Demo.txt"); } }
2.在Config类中配置信息:
@Bean(initMethod = "open",destroyMethod = "close") public DemoLogger logger(){ return new DemoLogger(); }
3.编写测试案例:
@Test public void testDemoLogger(){ DemoLogger logger = ctx.getBean("logger", DemoLogger.class); logger.out.println("Hi"); logger.out.println("Test!"); }
测试结果:
打开文件Demo.txt 20:50:04.550 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'logger' 打开文件Demo.txt 20:50:04.568 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean' 初始化 20:50:04.599 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@668bc3d5, started on Fri Oct 29 20:50:04 CST 2021 关闭文件Demo.txt 关闭文件Demo.txt 销毁 /** * 刷新项目文件目录后可以在测试文件DemoLogger.txt中找到输出结果:Hi Test! * 显然在控制台上出现了上一个案例中的“打开文件Demo.txt”信息,原因是Spring采用“立即初始化” * 方式创建了对象 */
测试案例:测试 @Scope("prototype")时候destroyMethod不生效现象
1.5.3 懒惰初始化
在@Component注解下加了@Lazy注解
package cn.tedu.pojo; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Component @Lazy public class Person { public Person(){ System.out.println("创建了Person"); } @Override public String toString() { return "良子哥"; } }
测试案例:
@Test public void testPerson(){ Person person = ctx.getBean("person", Person.class); System.out.println(person); //区别在于调用和不调用person的结果 System.out.println("OK"); }
测试结果:
不调用时:
调用时
在@Bean下加@Lazy注解
@Bean @Lazy public Student student(){ return new Student();
测试案例:
@Test public void testStudent(){ Student student = ctx.getBean("student", Student.class); System.out.println(student); //区别在于调用或者不用调用student的结果 System.out.println("OK"); }
测试结果:
调用情况下:
不调用情况下:
1.5.3 @Import
当公司两个程序员要合并配置文件时。一般情况下会出现配置文件覆盖的情况,这时就需要人工合并配置文件,将里面的Bean对象放到一起,实现合并。但是人工合并却很费时间,浪费人才资源。这时出现了该注解。可以将两人的配置文件合并在一起。
案例:
创建一个新的配置文件SysConfig配置文件(在不同包下)
package cn.tedu.sys; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Date; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Configuration /** * 系统管理模块配置信息 * */ public class SysConfig { @Bean public Date myDate(){ return new Date(); } }
将上面的配置文件导入到Config配置文件中
package cn.tedu.demo; import cn.tedu.pojo.DemoLogger; import cn.tedu.pojo.Student; import cn.tedu.sys.SysConfig; import org.springframework.context.annotation.*; /** * @Author Mr WeiLiang * @Date 2021/8/5 0005 09:22 * @Version 1.0 */ @Configuration //此类为配置文件 @ComponentScan(basePackages = "cn.tedu.pojo") //指定被扫描的包 @Import({cn.tedu.sys.SysConfig.class}) //合并SysConfig配置文件,如果有多个,在后面 //加逗号继续添加 public class Config { @Bean(initMethod = "open",destroyMethod = "close") //@Scope("prototype") public DemoLogger demoLogger(){ return new DemoLogger(); } @Bean /** * 告诉spring在启动时候,加载被@#Bean标准的方法 * 返回值是spring创建的对象,方法名是Bean的ID * */ public Demo bean(){ return new Demo(); } @Bean @Lazy public Student student(){ return new Student(); } }
测试案例
@Test public void testMyDate(){ Date date = ctx.getBean("myDate", Date.class); System.out.println(date); }
测试结果
打开文件Demo1.txt 13:32:55.835 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean' 初始化 Sat Oct 30 13:32:55 CST 2021 //系统当前时间 13:32:55.866 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@668bc3d5, started on Sat Oct 30 13:32:55 CST 2021 关闭文件Demo1.txt 关闭文件Demo.txt //可以调用SysConfig中的Bean方法,输出当前系统的时间
Spring-IOC
最新推荐文章于 2022-09-18 19:20:37 发布