目录
1、什么是Spring框架?
Spring框架是由于开发的复杂性而创建的,使用基本的JavaBean代替EJB;
Spring框架还是一个轻量级的控制反转和面向切面的容器框架;
Spring框架使用于包括服务器开发等的任何Java应用,使得Java程序更加便捷、高效、安全
2、什么是Spring容器或者叫SpringBean容器?
Bean就是 Java对象,容器就是对Java对象的整个生命周期进行管理(包括创建、装配、销毁).
3、Spring的模块化组成结构
3.1. Core Container(核心容器)
3.1.1 IoC(控制反转)
实现了IoC思想的容器叫做IoC容器,由IoC容器来管理对象的生命周期和依赖关系等,降低了代码的耦合程度(以前手动new对象并设置属性,控制权掌握在应用程序自身,现在由容器来统一管理对象,这种控制权的转移,叫做控制反转).
3.1.2 DI(依赖注入)
DI是实现IoC的方法之一,由IoC容器在运行期间动态的将某种依赖关系注入到对象中.
依赖注入的三种方式:
构造函数方法注入、Setter方法注入与接口注入。
3.1.3 注册Bean的方法
- 在类上使用以下四个注解
@Controller
@Service
@Repository
@Component
当使用以上注解的类被Spring扫描到时就会创建Bean对象并注册到容器中,默认类名首字母小写作为Bean的名称或叫id.
传统的三层架构设计:Controller(控制层)、Service(服务层)、Repository(数据访问层).
@Controller 用于web请求和响应的处理,完成请求数据的校验等操作;
@Service用于业务逻辑处理,根据方法参数完成业务逻辑;
@Repository用于关系型数据库的访问操作;
其他组件使用@Component.
该方法只能注册一个Bean对象.
- 在方法上使用注解:@Bean
当该类被Spring扫描到时,可以在方法上使用@Bean注解,通过方法返回类型,默认使用方法名作为Bean的名称.
该方法比较灵活,可以手动设置属性,可以注册多个Bean对象.
- 在类上使用注解:@Configuration
注册一个配置类到容器,一般用来定义配置某些资源.
- 实现FactoryBean接口,在类上使用@Component注解
FactoryBean以Bean结尾,表示它是一个Bean,而且是一个实现了FactoryBean接口的Bean,
注册一个Bean对象的工厂类,实现了 FactoryBean接口,获取Bean对象时,根据该Bean的id从容器中获取的实际是FactoryBean的 getObject()方法返回的对象,而不是 FactoryBean本身,如果要获取 FactoryBean对象,请在 id前面加一个&符号来获取.
示例:如下先定义一个Bean,实现 FactoryBean接口,指定泛型为User类,会将 getObject() 方法的返回对象注册到容器中.
package org.example.model;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
@Component
public class ByFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
User user = new User();
user.setUsername("abc");
user.setPassword("123");
return user;
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
因为已经定义过User对象了,所以只能通过 id 获取,通过类型获取会报错。
3.1.4装配Bean的方法
@Autowired
@Resource
@Autowired注解的使用
①属性注入:在属性上使用@Autowired注解可以将该对象从容器中装配到属性中;
在setter方法上使用@Autowired注解可以将Bean对象注入到方法参数,然后装配到属性中;
②构造方法注入:同样在构造方法上使用@Autowired注解可以将Bean对象注入到方法参数,然后装配到属性中.
使用@Autowired装配Bean对象时,如果容器中有多个该类型的Bean就会出错,这时可以使用@Qualifier注解指定Bean对象名字,根据名字装配到指定对象:
@Autowired
@Qualifier(“对象名”)
@Autowired和@Resource的区别
@Autowired是Spring提供的注解,只能在Spring框架中使用,Resource是jdk官方提供的注解,Spring的DI提供了该注解的实现.
3.1.5 获取Bean对象
定义好了Bean对象,注册到容器中以后就可以获取Bean对象了,获取Bean对象有两种方式:
通过类型获取:该类型的Bean只有一个才能使用;
通过名称获取:同类型的Bean有多个也可以获取.
4、Spring容器使用流程
1)启动容器
2)根据配置完成Bean初始化
3)注册Bean对象到容器中
4)装配Bean的属性
写一个入口类并使用名称和类型两种方式获取Bean对象:
package org.example;
import org.example.config.AppConfig;
import org.example.controller.LoginController;
import org.example.dao.LoginDAO;
import org.example.model.User;
import org.example.service.LoginService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
//根据Spring配置文件路径创建容器:应用上下文对象
ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
//获取注册的Bean对象:
// 根据名称获取
LoginController loginController1 = (LoginController) context.getBean("loginController");
//根据类型获取
LoginController loginController2 = (LoginController) context.getBean(LoginController.class);
//获取到的是同一个对象
System.out.println(loginController1 == loginController2);
//关闭容器
((ClassPathXmlApplicationContext) context).close();
}
}
Spring容器的API有BeanFactory和ApplicationContext两大类,它们都是顶级接口,其中ApplicationContext是BeanFactory的子接口,这里我们使用的是ApplicationContext的上下文接口.
5、Bean的作用域
可以在类上使用@Scope注解来设置Bean的作用域,比如:
@Scope(“prototype”)设置作用域为原型模式.
1)singleton
(单例模式)
该作用域下的Bean在IoC容器中只存在一个实例:获取Bean(即通过
applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是同一个对象。
场景:通常无状态的Bean使用该作用域(无状态表示Bean对象的属性状态不需要更新)
例如:
备注:Spring默认选择该作用域
2)prototype
(原型模式)
每次对该作用域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是新的对象实例。
场景:通常有状态的Bean使用该作用域
3)request
每次http请求会创建新的Bean实例,类似于prototype
场景:一次http的请求和响应的共享Bean
备注:限定SpringMVC中使用
4)session
在一个http session中,定义一个Bean实例
场景:用户回话的共享Bean, 比如:记录一个用户的登陆信息
备注:限定SpringMVC中使用
5)application
在一个http servlet Context中,定义一个Bean实例
场景:Web应用的上下文信息,比如:记录一个应用的共享信息
备注:限定SpringMVC中使用
6)websocket
在一个HTTP WebSocket的生命周期中,定义一个Bean实例
场景:WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean。
备注:限定Spring WebSocket中使用
6、Bean的生命周期
Bean的生命周期分为四个阶段:实例化、属性注入、初始化、销毁。
Bean自身的方法:比如构造函数、getter/setter 以及 init-method 和 destory-method。
容器级生命周期方法:主要是后处理器方法,比如的 InstantiationAwareBeanPostProcessor、BeanPostProcessor 接口方法。这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。在 Spring 容器创建任何 Bean 的时候,这些后处理器都会发生作用。
Bean级生命周期方法:可以理解为 Bean 类直接实现接口的方法,比如 BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean 等方法,这些方法只对当前 Bean 生效。
-
实例化
-
属性注入
注入Aware接口的方法参数对象,按如下顺序注入:
BeanNameAware接口只有一个方法setBeanName,用来获取bean的id或name
BeanFactoryAware接口只有一个方法setBeanFactory,用来获取当前环境的BeanFactory
ApplicationContextAware接口只有一个方法setApplicationContext,用来获取当前环境的ApplicationContext
InitializingBean接口只有一个方法afterPropertiesSet(),在属性注入完成后调用
- 初始化
初始化前,执行BeanPostProcessor的Before方法
初始化时,实现InitializingBean接口方法,还可以通过@PostConstruct注解或者xml配置init-method方法指定初始化方法。
初始化后,执行BeanPostProcessor的After方法
初始化完成后,singleton bean 和 prototype bean的处理不同:
- 销毁(指singleton bean)
Spring容器关闭时,Bean对象被销毁,执行销毁方法:
或者使用@PreDestroy注解指定销毁时要执行的销毁方法。
DisposableBean接口只有一个方法destory,在容器销毁时调用
整个过程由Spring容器自动管理,其中我们可以自定义初始化方法init-method和销毁方法destroy-method。
调用顺序:
BeanNameAware
BeanFactoryAware
ApplicationContextAware
BeanPostProcessor Before
@PostConstruct
InitializingBean
init-method:注解使用@Bean(initMethod=“方法名”),xml使用
BeanPostProcessor After
@PreDestroy
DisposableBean
destroy-method:注解使用@Bean(destroyMethod=“方法名”),xml使用
两个比较:
1.BeanFactory和ApplicationContext之间的区别
BeanFactory是最底层的容器接口,只提供最基础的容器功能(包括Bean的实例化和依赖注入,并且使用懒加载的方式,Bean只有在通过调用getBean()方法直接调用时才实例化);
ApplicationContext是BeanFactory的子接口,与BeanFactory懒加载的方式不同,它默认是预加载,每个Bean都在ApplicationContext启动后实例化,但可以自己设置成懒加载.
2.BeanFactory和FactoryBean之间的区别
BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似.