一、什么是Spring?
Spring是包含许多工具方法的ioc容器。
那么,什么又是ioc容器呢?
ioc容器是控制翻转的意思。
例如在传统的程序开发中构建一个小汽车:
这样轮胎的属性值发生改变之后,依赖其的底盘、车身和汽车都需要发生修改,代码开销大。
但是控制翻转的思想是注入传递的方式,将轮胎对象逐级向上传入,这样底层代码发生改变时,整个调用链无需改变,使代码之间解耦,程序设计更加灵活。
说到ioc那么就必须提起DI,DI是依赖注入,就是在ioc容器运行期间,动态的将某种依赖关系注入到对象之中,ioc的控制翻转和DI的依赖注入是从不同角度去描述同一件事情,ioc是指导思想,那么DI就是具体实现。
Spring既然是一种容器,那么其核心功能就是将对象存入其中以及从Spring中取出对象。
二、创建Spring项目
创建Spring项目,总体可以分为以下三步:
- 创建maven项目;
- 添加Spring框架支持;
- 创建启动类。
首先创建maven项目:
在pom.xml中引入Spring框架支持:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.3.RELEASE</version> </dependency> </dependencies>
添加启动类:在java文件夹下创建一个启动类,其中添加了main方法:
public class Test { public static void main(String[] args) { System.out.println("hello test"); } }
三、添加Bean对象
1、创建一个Bean对象
就是创建一个任意类即可。
public static void sayHi(String str){ System.out.println("hi"+str); }
2、将Bean对象添加到容器中
首先需要在resources文件夹下创建一个spring-config.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"> </beans>
将Bean对象添加到容器中就需要在spring-config的文件中增加一对bean标签,其属性id指定为对象名,采用小驼峰命名,class为其所在包名+类名,例如:
<bean id="user" class="com.beans.User"></bean>
四、获取Bean对象
1、获取Spring上下文
a、使用ApplicationContext接口来接收ClassPathXmlApplicationContext()对象,其中需传入的参数为resources下的.xml文件名,就可获取Spring上下文对象。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
b、使用BeanFactory来接收XmlBeanFactory(new ClassPathResource()),其中ClassPathResource中的参数也是resources下的.xml文件名。
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
ApplicationContext和 BeanFactory的区别:
- ApplicationContext是BeanFactory的子类,其功能相对比较完善。
- BeanFactory是按需加载Bean对象,ApplicationContext是一次性加载完所有的Bean对象,因此BeanFactory相比更加轻量。
2、获取指定的Bean对象
可以使用Spring上下文对象的getBean方法,其方法有多种,常用的传入参数为spring-config的id名,和类名.class。
User user = factory.getBean("user",User.class);
3、使用Bean对象
对获取到的Bean对象可以正常调用其属性和方法。
user.sayHi("factory");
运行结果:
五、Spring更简单的存储和读取Bean对象
1、存入Bean对象
添加配置路径
改变之前利用bean标签来存储Bean对象的形式,在spring-config文件中新增<content:component-scan base-package="com.beans"></content:component-scan>来配置扫描路径。
添加存储Bean对象的注解
类注解:@Controller(控制器)、@Conponent(组件)、@Service(服务)、@Resposity(仓库)、@configuration(配置)
使用注解,可以使代码的可读性提高。
在这五大类注解中,@Component 是其他四类注解的父类。
方法注解:@Bean可将方法返回的对象进行存入,但是仍需搭配类注解使用。
@Bean方法注解也可对对象进行重命名,设置name属性即可:
@Controller public class User { @Bean(name="userinfo") public User getUser(){ return new User(); } public void sayHi(String str){ System.out.println("hi! "+str); } }
但是在使用Bean设置name属性之后,只能通过设置的name属性值来获取对象,不能使用方法名。
解决将一个类型的对象多次注入的问题:
- 精确描述要注入的名称,要注入的对象名与Spring当中的一致;
- 使用@Resource注解设置name属性重命名注入对象;
- 使用@Autowired注解和@Qualifier设置value属性值的方式重命名注入对象。
2、读取对象
对象注入(从容器中将对象读取出来)的三种方式:
- 属性注入;
- 构造方法注入;
- Setter注入;
属性注入
属性注入基于@Autowired来实现,在该类之前应该加上@Controller注解,在被注入的对象的类之前加上Service注解:
@Controller public class UserController { @Autowired private User user; public void sayHi(){ user.sayHi("UserController"); } } @Service public class User { public void sayHi(String str){ System.out.println("hi! "+str); } }
在main方法调用如下:
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); UserController userController = context.getBean(UserController.class); userController.sayHi(); }
构造方法注入
在类的构造方法实现注入,在类的构造方法前加上@Autowired注解,如果类的构造方法只有一个则可省略@Autowired注解,若有多个则必须指明。
@Controller public class UserController { private User user; @Autowired public UserController(User user){ this.user = user; } public void sayHi(){ user.sayHi("UserController"); } }
Setter注入
创建Set方法,并且使用@Autowired注解完成对象注入。
@Controller public class UserSetter { private User user; @Autowired public void setter(User user){ this.user = user; } public void sayHi(){ user.sayHi("Setter"); } }
属性注入、构造方法注入和Setter注入的区别:
- 属性注入的写法简单,但是只是适合ioc容器;
- Setter注入是之前Spring的推荐写法,但是Setter相比构造方法没有更加通用;
- 使用构造方法注入时其通用性更好,并且能确保要注入的对象一定初始化过了,但是在构造方法的参数过多时就需要检测是否符合单一设计原则的规范,并且次注入方法也是后期Sprig比较推荐的写法。
在进行类注入时,除了可以使用@Autowired注解时,还可以使用@Resource注解,那么这两个注解又什么区别?
- @Autowired来源于Spring注解,@Resource来源于JDK注解;
- 相比@Autowired,@Resource注解更多的参数设置;
- @Autowired注解可以使用属性注入、构造方法注入和Setter注入,但是@Resource注解只能用于属性注入和Setter注入。
六、Bean的作用域
Bean的作用域:bean在Spring框架中的某种行为。
Bean的作用域类型有:
- singleton:单例模式(默认)
- prototype:原型模式(多例模式)
- request:请求作用域(SpringMVC)
- session:会话作用域(SpringMVC)
- application:全局作用域(SpringMVC)
- websocket:HTTP WebSocket作用域(Spring webSocket)
设置Bean作用域的方式:
- 通过@Scope("")注解来进行设置
- 通过枚举类型来进行设置@Scpoe(ConfigurableBeanFactory.SCPOE_SINGLETON)
七、Bean的生命周期
Bean的生命周期如下:
实例化:分配内存空间;
设置属性:注入对象;
初始化:
- 执行各种通知;
- 执行前置方法;
- 执行两种构造方法:postConstructer、init-method
- 执行后置方法;
使用bean;
销毁Bean:
- 使用@PreDestroy注解
- 重写DisposableBean接口方法;
- distory-method;