spring的核心功能就是ioc和aop
一:什么是IOC?
IOC - 控制翻转(思想),将创建对象的权利交给第三方(IOC容器 - BeanFactory)。
二: 为什么需要将创建对象的权利交给第三方?自己创建有什么问题吗?
解耦
解耦有什么好处? 在编程过程中,A类中直接new B类的对象,这种行为称之为硬编码耦合。硬编码耦合不会对业务造成任何影响,但是增加了A类和B类之间的关联程度(耦合性),假设在后续的维护过程中,因为系统的升级,需要改变B类的构造形式(比如构造方法发生了变化),这时除了要修改B类本身的代码之外,还要去调整A类的代码。如果还有很多类new了B类,那么也就意味着这些类都需要一一修改,极大的增加了程序的维护成本。IOC就是为了解除这种耦合性,所设计的思想。
Servlet{
private IService=new ServiceImpl();
}
假如Servlet是A类ServiceImpl是b类
A类和b类和ioc的容器的关系,就有点像注册中心和微服务的关系;现在全部的类都交给ioc容器管理,现在A类要调b类直接去ioc容器告诉我b类,直接去调就好了,假如b类的构造形式发生了变化和a类没有关系,唯一变化是ioc容器,至于是什么构造出来的也和a类也没有关系
AOP - 面向切面编程(思想),在实际开发过程中,有很多业务需要处理,往往每个业务都可以拆分成核心业务与非核心业务,每个业务的核心业务必然不同,但是非核心业务却往往有相同的部分(比如事务的开启与提交、日志的管理、程序的监控、资源的回收......),将非核心业务提取出现,形成一个个的切面,开发者在开发过程中只需要关注核心业务部分即可,程序在运行时,将非核心业务(切面)与开发者的核心业务代码重新组织在一起,形成完整的业务,这种针对一个个切面的编程方式就称之为面向切面编程。
3.1 AOP的核心实现
动态代理 - JDK动态代理、Cglib动态代理
动态代理和静态代理的区别?
静态代理需要自己新建代理类,创建代理对象,动态代理无需为每个类创建代理类, 而是自动的生成代理对象。
静态代理
动态代理的使用场景:
比如在controller层,都会有类似的调用业务层接口,private IHotalService hotalService,然而实现类上有一个事务管理,要使用事务管理就要使用动态代理对象这个时候注入的就是代理对象不在是实现类了 ,那么这个时候 hotalService这个接口已经是动态代理对象,这就是所谓的构造形式发生变化,所以我们发现没有ioc、aop都不好用了
动态代理
spring底层是如何实现的?
哪些bean需要被spring管理,那这个配置信息有xml、注解、java配置类,IOC容器有一个配置解析器(BeanDefinitionReader)接口,这个接口会解析配置文件根据配置生成Bean的BeanDefinition对象放入初始化的BeanFactory的map中。其实这个地方spring的设计也没有那么的规范,因为BeanDefinitionReader接口是用来读取配置的规范接口,但是他里面的子类没有读注解的子类,只有读配置xml的子类、读properties的配置文件的子类。注意BeanDefinition对象不是bean对象,而且BeanDefinition也不包含bean对象,这个时候bean还没有new呢,因为后面会有n个BeanFactoryPostProcessor对BeanFactory做一些后置处理,那么你的beanfactory首先要经过这一些列的后置处理器,然后bean工厂才算准备 完成。BeanFactoryPostProcessor在封装mq得到时候用过,这个工具方法的作用是什么呢?就是人为的往beanfactory丢对象。BeanFactoryPostProcessor是一个拓展思维他有可以没有也可以。
beanfactory准备完成之后就是进入初始化bean的过程其实就是生命周期。那怎么初始化呢?一定要调用目标bean的构造方法,这个构造方法是通过反射实现的。调用了构造方法之后还要解决属性的依赖注入的问题,通过反射,和递归解决,为什么要用递归呢?因为有时候你要的bean,spring容器里面还没有加载过来,这个过程会从spring容器里beannames拿到里面的bean对象,(这个地方有可能会产生喜欢依赖的问题),然后调用bean进行初始化,我们为什么要用init-method <bean id="xxx" class="xxx.xxx.xx" init-method="xxx">,init-method的注解的写法是@PostConstruct,的方式进行初始化呢?而不用构造方法初始化?其实这个顺序已经很能说明问题了,如果在controller层调用service接口,用这个接口调用业务是会出空指针异常的,因为这个调用是在调用目标bean的构造方法,属性还没有依赖注入呢,要在方法上写个@PostConstruct注解就没有问题了。