Spring是一个轻量级的IoC和AOP容器框架,提供了IoC和AOP两大能力,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。主要包括以下七个模块:
Spring 的优点
IoC(Inversion of Control)控制反转,指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。
最直观的表达就是,以前创建对象的时机和主动权都是由自己把控的,如果在一个对象中使用另外的对象,就必须主动通过new指令去创建依赖对象,使用完后还需要销毁(比如Connection等),对象始终会和其他接口或类耦合起来。而 IOC 则是由专门的容器来帮忙创建对象,将所有的类都在 Spring 容器中登记,当需要某个对象时,不再需要自己主动去 new 了,只需告诉 Spring 容器,然后 Spring 就会在系统运行到适当的时机,把你想要的对象主动给你。也就是说, 对于某个具体的对象而言,以前是由自己控制它所引用对象的生命周期,而在IOC中,所有的对象都被 Spring 控制,控制对象生命周期的不再是引用它的对象,而是Spring容器,由 Spring 容器帮我们创建、查找及注入依赖对象,而引用对象只是被动的接受依赖对象,所以这叫控制反转。
DI:依赖注入,把对应的属性的值注入到具体的对象中,最简单的方式@Autowired,等完成属性值的注入。
IoC原理: Spring 的 IoC 的实现原理就是工厂模式加反射机制,而在 Spring 容器中,Bean 对象如何注册到 IoC 容器,以及Bean对象的加载、实例化、初始化详细过程可以阅读这篇文章:Spring的Bean加载流程_张维鹏的博客-CSDN博客
OOP面向对象,允许开发者定义纵向的关系(互相调用),但并不适用于定义横向的关系,会导致大量代码的重复,而不利于各个模块的重用。
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理。
实现方式:目前流行的AOP框架有两个,分别为Spring AOP
和AspectJ
。Spring AOP使用纯Java实现,不需要专门的编译器和类加载器,在运行期间通过代理方式向目标类植入增强的代码。AspectJ是一个基于Java语言的AOP框架,从Spring2.0开始,Spring AOP引入了对AspectJ的支持,AspectJ扩展了Java语言,提供了专门的编译器,在编译时提供横向代码的植入。
在Spring AOP中,实现AOP的方式是动态代理。而实现动态代理有两种方式:JDK动态代理和CGLIB动态代理。Spring根据是否实现被代理接口来选择使用JDK动态代理还是CGLIB动态代理。详见:
JDK动态代理和CGLIB动态代理
AOP概念、相关术语、AOP实战(基于AspectJ实现)、Adice类型及执行顺序、切入点表达式写法
详细内容可以阅读这篇文章:Spring容器的启动流程
1、初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中:
- ① 实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
- ② 实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
- ③ 实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象
2、将配置类的BeanDefinition注册到容器中:
3、调用refresh()方法刷新容器:
- ① prepareRefresh()刷新前的预处理:
- ② obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory:
- ③ prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件:
- ④ postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置
- ⑤ invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器:
- ⑥ registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
- ⑦ initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析:
- ⑧ initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到:
- ⑨ onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑
- ⑩ registerListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件:
- ⑪ finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象;
- ⑫ finishRefresh():发布BeanFactory容器刷新完成事件:
BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。区别如下:
ApplicationContext常用的三个实现类
Spring Bean的生命周期指的是一个普通的Java类变成Bean的过程,大致流程是:在创建Bean时,Spring会扫描指定包下面的Java类,然后根据Java类构建BeanDefinition
对象,然后再根据BeanDefinition
来创建Spring的bean,特别要记住一点,Spring是根据BeanDefinition
来创建Spring bean的。
通过ClassPathXmlApplicationContext和AnnotationConfigApplicationContext类将XML定义或者注解定义的的Bean读取成统一的Bean规范,即BeanDefinition(BeanDefinition是Spring的一个核心接口,它封装了生产Bean的一切原料,关于Bean生产的一切定义都在BeanDefinition类里。),存放多个BeanDefinition的Map是BeanDefinitionMap,BeanDefinitionMap中的BeanDefinition由BeanDefinitionRegistry负责注册成Bean。最后由Spring的顶层核心接口BeanFactory负责生产Bean(通过getBean方法)。
大体上,Bean的什么周期分为以下几个步骤:
Java类变成BeanDefinition
的过程,重点关注AbstractApplicationContext类中的refresh方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing. 准备工作包括设置启动时间,是否激活标识位,
// 初始化属性源(property source)配置
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//返回一个factory 为什么需要返回一个工厂
//因为要对工厂进行初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//准备工厂
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//这个方法在当前版本的spring是没用任何代码的
//可能spring期待在后面的版本中去扩展吧
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//在spring的环境中去执行已经被注册的 factory processors
//设置执行自定义的ProcessBeanFactory 和spring内部自己定义的
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//注册beanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
//初始化应用事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
有关Spring Bean生命周期最主要的方法有三个invokeBeanFactoryPostProcessors、registerBeanPostProcessors和finishBeanFactoryInitialization(重要?)。
postProcessBeanDefinitionRegistry
方法,该步骤会扫描到指定包下面的标有注解的类,然后将其变成BeanDefinition对象,然后放到一个Spring中的Map中,用于接下来创建Spring bean的时候使用这个BeanDefinition。Spring中Bean的生命周期大致如下:
public interface BeanPostProcessor {
//在每一个bean对象的初始化方法调用之前回调
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//在每个bean对象的初始化方法调用之后被回调。
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
singleton
(单例)的,也就是使用Singleton模式产生单一实例,Spring会帮我们管理单例模式Bean的完整生命周期,容器关闭Singleton的bean也就跟着销毁了。而对于scope=prototype
的bean,Spring在创建好交给使用者之后则不会再管理后续的生命周期,而是交给JVM的垃圾回收机制(GC)来管理Bean的生命周期。
@Component(value = "accountService")//默认名称是accountServiceImpl
@Scope(value = "singleton")//默认为singleton,可以不写
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
public void saveAccount() {
accountDao.saveAccount();
}
@PostConstruct
public void init_method(){
System.out.println("初始化方法执行了");
}
@PreDestroy
public void destroy_method(){
System.out.println("销毁方法被执行了");
}
}
public static void main(String[] args) {
//1.获取核心容器对象
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取Bean对象
AccountService accountService = (AccountService) classPathXmlApplicationContext.getBean("accountService");
//3.打印获取的对象
System.out.println(accountService);
classPathXmlApplicationContext.close();
}
运行结果:
初始化方法执行了
com.xingze.service.impl.AccountServiceImpl@166fa74d
十月 29, 2019 9:26:44 上午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4d76f3f8: startup date [Tue Oct 29 09:26:43 CST 2019]; root of context hierarchy
销毁方法被执行了
分析:容器在关闭后,scope=singleton
的Bean也就跟着销毁了。
2、将@Scope(value = "singleton")
改为@Scope(value = "prototype")
,运行结果如下:
初始化方法执行了
com.xingze.service.impl.AccountServiceImpl@166fa74d
十月 29, 2019 9:32:18 上午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4d76f3f8: startup date [Tue Oct 29 09:32:17 CST 2019]; root of context hierarchy
可以看出,配置为scope=prototype
的bean在容器关闭之后仍然存在,销毁方法并没有执行。