Spring
Spring IOC
Q:IOC你了解吗
Q:IOC概念
Spring Core最核心的部分
- 首先要介绍一种思想:依赖倒置原则。依赖倒置原则是把原来高层建筑依赖底层建筑倒置过来,变成底层建筑依赖高层建筑,这样不会出现“牵一发而动全身”的情况。
- IOC是就是依赖倒置原则的一种设计思路,就是将原本在程序中自己手动创建对象的控制权,交由Spring框架来管理。Spring框架负责控制对的生命周期和对象之间的关系。
- 具体采用的方式是依赖注入。依赖注入就是把底层类作为参数传入到上次类,实现上层类对底层类的控制。依赖注入主要有以下方法:构造器注入、setter方法注入、接口方式注入和注解注入。
- Spring的IOC容器就是具有依赖注入功能的容器,负责实例化、配置对象以及他们之间的依赖。
Q:Spring IOC容器管理Bean流程
- Spring启动时会读取Bean配置信息(XML;@Configuration的类;注解@Autowired)
- 在Spring容器中生成一份相应的Bean注册表。
- 利用java的反射功能根据注册表去实例化Bean。
- 将实例化的Bean放入Bean缓存池中。
Q:Spring IOC容器功能
依赖注入 ; 依赖检查 ; 自动装配 ; 支持集合 ; 指定初始化和销毁方法 ; 回调方法
Q:Spring IOC容器的核心接口
BeanFactory
- 提供IOC的配置
- 包含了Bean的定义,便于实例化Bean,控制Bean的生命周期(提供了最基本的依赖注入功能)
- 建立了Bean之间的依赖关系
- 提供了延迟注入
- 启动更快
ApplicationContext(继承多个接口)
- BeanFactory 管理和装配Bean
- ResourcePatternRolver 能够加载资源文件
- MessageSource 管理消息,实现国际化
- ApplicationPublisher 能够注册监听器,实现监听机制
Q:Spring IOC容器装配Bean的方法
XML配置方式
笼统说就是在定义好实体类之后,在applicationContext.xml文件中配置bean信息(包含id和对应的class),这样相当于把bean装载到Spring容器中了。
然后可以通过读取配置信息得到ApplicationContext的对象,调用它的getBean方法(里面可以根据类型查找Bean或者根据id查找)得到对应的bean。
依赖注入的实现:set方法、构造函数、注解、接口(不推荐)
Set方法:
在需要注入的类里定义被注入类,然后通过set方法将被注入类传参,同时applicationContext配置文件中添加下面内容
构造函数:
在需要注入的类里定义被注入类,然后通过构造函数将被注入类传参,同时applicationContext配置文件中添加下面内容
基于注解
@Component 和@CompomentScan搭配扫描装配Bean。同时可以在实体类里用@Value初始化对象的属性。
使用@Autowired实现依赖注入
基于Java类
先写一个配置信息类用@Configuration标注,然后编写一个返回Bean实例的方法并用@Bean标注。
使用@Autowired实现依赖注入
Q:getBean()源码逻辑
AbstractBeanFactory中的getBean(),又调用了doGetBean()
1.通过transformedBeanName提取beanName
2.根据getSingleton(beanName)获取单例bean(也就是缓存中)
3.实例化bean
4.如果获取不到bean就检测parentBeanFactory
5.递归初始化依赖的bean
6.创建bean
Q:Spring bean作用域
singleton:
Spring的默认作用域,容器里拥有唯一的Bean实例
prototype:
针对每个getBean请求,容器都会创建一个Bean实例
request:
会为每个Http请求创建一个Bean实例
session:
会为每个session创建一个Bean实例
globalSession:
会为每个全局Http Session创建一个Bean实例,该作用域仅对Portlet有效
Q:Spring bean生命周期
• Bean容器找到配置文件中Spring Bean的定义。
• Bean容器利用Java Reflection API创建一个Bean的实例。
• 如果涉及到一些属性值 利用set方法设置一些属性值。
• 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
• 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
• 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
• 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
• 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
(对实例化的bean添加一些自定义的处理逻辑,AOP,前置初始化方法)
• 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
• 如果Bean在配置文件中的定义包含init-method属性,执行初始化相关工作。
• 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
(AOP,后置初始化方法)
• 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
• 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
Spring AOP
Q:Spring AOP你了解吗
Q:AOP概念
面向切面编程AOP是基于关注点分离的技术实现的,主要是将业务逻辑代码和通用化代码(日志,事务等)的关注点分离。通用化代码的实现就是(切面)。业务功能代码和切面代码分开后,架构将高内聚低耦合。为了确保功能的完整性,切面最终需要被合并到业务中(织入)。
Aspect:通用代码的实现
Target:被织入通用代码的对象
Join Point:可以作为切入点的机会
Pointcut:切入点
Adivice:通知,类里的方法
Weaving:Aop的实现过程
Q:AOP织入方式
编译时织入:需要特殊的Java编译器,如AspectJ
类加载织入:需要特殊的Java编译器,如AspectJ
运行时织入:Spring采用的方式,通过动态代理实现
Q:AOP的实现机制
由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认策略如果目标类是接口,则用JDKProxy来实现,否则用Cglib。
JDKProxy的核心:InvocationHandler接口和Proxy类(反射)
Cglib:以继承的方式动态生成目标类的代理。
Q:Spring里的代理模式的实现
真实实现类的逻辑包含在了getBean方法里。
getBean方法返回的实际上是Proxy的实例。
Proxy实例是Spring采用JDK Proxy或CGLIB动态生成的。
Q:Spring AOP 和AspectJ AOP区别
Spring AOP属于运行时增强(动态),基于代理;AspectJ AOP属于编译时增强(静态),基于字节码。
Spring AOP已经集成了AspectJ,AspectJ应该算的上是Java生态系统中最完整的AOP框架了。AspectJ相比于SpringAOP功能更加强大,但是Spring AOP相对来说更简单,如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择AspectJ,它比Spring AOP快很多。