概念
- IOC 定义:控制反转 IoC is also known as dependency injection (DI)
- Spring-framework官网针对IOC、DI 的描述
- DI定义:依赖注入
- 自动注入:配置的类属性按类型装配,没找到,属性为null, default-autowire=“byType”
如果一个类中的属性,并且提供了这个属性的set方法,通过这个类的属性的类型去容器中去找,
<?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-4.2.xsd" default-autowire="byType">
<bean id="zlService" class="com.zfx.service.ZLService"/>
<bean id="lbService" class="com.zfx.service.LubanService"/>
</beans>
- bean初始化流程
AnnotationConfigApplicationContext -> refresh() -> finishBeanFactoryInitialization(beanFactory) ->beanFactory.preInstantiateSingletons() ->getBean(beanName) ->doGetBean -> createBean -> doCreateBean-> populateBean(设置属性) - 动态代理的原理
- BeanDefinition extends AttributeAccessor, BeanMetadataElement
BeanDefinition : 描述类的元信息
AttributeAccessor: 对类的原信息没有的属性进行扩展
BeanMetadataElement:描述该类在磁盘上的Java文件的位置信息
经典面试题
- 手动装配 @Autowired,XML中 ref 指定
① @Autowired, 先按名称在容器中查找注入,若找不到再按类型查找,在找不到,报错。 - spring注入方式有几种?
① set 注入
② 构造方法注入
spring的自动注入模型有几种? Autowiring modes,官方1.4.5 - spring 怎么体现默认支持循环依赖
① 单例,不能用构造方法注入,可以关闭循环依赖 - Spring中运用了哪些策略模式?
① bean工厂模式
② 策略模式: 在beanFactory的后置处理器,和 bean的后置处理器中使用(在完成bean的属性注入后,使用不同的后置处理器,)
![(https://img-blog.csdnimg.cn/20200605155802255.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjIzNTY1,size_12,color_FFFFFF,t_70))
/*
验证单例模式, 关闭循环依赖 异常信息:Error creating bean with name 'orderService': Requested bean is currently in creation: Is there an unresolvable circular reference?
*/
@Test
public void t7(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(AppConfig.class);
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ac.getBeanFactory();
beanFactory.setAllowCircularReferences(false); //禁止循环注入
ac.refresh();
}
```java
// 判断是否允许 循环依赖 this.allowCircularReferences 属性默认为 true(类:AbstractAutowireCapableBeanFactory)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
``
Model | 描述 |
---|---|
no | 没有使用自动注入 |
byName | 按名称查找注入 |
byType | 按类型查找注入 |
constructor | 推断构造方法注入,若构造方法存在多个时,使用构造方法属性在容器中存在的个数最多的一个构造方法 |
- Spring容器加载完成后,回调方法初始化方式
方式 | 描述 |
---|---|
InitializingBean | 实现该interface,实现afterPropertiesSet()方法 |
@PostConstruct | 使用该注解 |
init-method=“init” | bean标签上配置 |
注:若三种同时配置到一个bean上,优先级生效顺序如下:
注解> 实现接口 > xml中配置
-
FactoryBean和普通的bean有什么区别
-
如何把一个对象放入到spring容器当中
① ac.getBeanFactory().registerSingleton();
② implements FactoryBean -
BeanFactoryPostProcessor —bean 工厂的后置处理器 干预bean工厂的实例化过程
-
Spring AOP 包含哪些通知类型
① Before advice
② After returning advice
③ After throwing advice
④ After (finally) advice
⑤ Around advice -
AOP是什么
定义:与OOP相比,面向切面,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性的问题,这些横切性的问题与我们的主业务逻辑关系不大,这些横切性问题不会影响到主业务逻辑的实现,但是会散落到代码的各个部分,难以维护,AOP是处理一些横切性问题,AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的,使代码的重用性和开发效率提高。 -
AOP的应用场景
① 日志记录
② 权限验证
③ 效率检测
④ 事务管理
⑤ exception -
Spring中如何选择Cglib 和 jdk动态代理的
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config); //使用jdk代理
}
return new ObjenesisCglibAopProxy(config); // 使用CGLIB 代理
}
else {
return new JdkDynamicAopProxy(config);
}
}
① 当bean实现接口时,会用JDK代理模式,当bean没有实现接口,用cglib实现
② 可以强制指定使用哪种 <aop:aspectj-autoproxy proxyt-target-class=”true”/> 或者 proxyTargetClass = true, true表示强制使用cglib
- Spring 通过构造方法实例bean 的原理?
① 首先实例化这个对象
② 推断构造方法- 手动注入:调用 determineConstructorsFromBeanPostProcessors 方法第一次推断构造方法,分几种情况, 如果没有构造方法----- 该方法返回为Null,用默认的无参构造
1.1 如果提供了默认的构造方法只有这一个 ---- 为null ---- 使用默认的
1.2 如果提供了多个构造方法,— 该方法返回null,— 迷茫 ---- 使用默认的构造方法
1.3 如果提供了多个构造方法,且指定为 @Autowired(required = true), 异常, 不知道该选哪个
1.4 如果提供了多个构造方法,且指定为@Autowired(required = false),表示使用这几个都有可能用,则返回多个,— 进行再次的 B推断----
1.5 提供了一个构造方法且不是默认的构造— 返回1个,用这个提供的构造方法 - 自动注入(推断B):推断出一个最优的构造方法 , 获取该构造方法中 有效的参数值 个数最多的一个构造方法。 若提供的构造方法参数个数一致(提供了多个模糊的构造方法),(即通过算法计算构造方法的参数差异值一样),判断系统配置的 是否采用严禁的构造,默认是宽松的。宽松的选其中一个,严禁的话直接报异常。
- 手动注入:调用 determineConstructorsFromBeanPostProcessors 方法第一次推断构造方法,分几种情况, 如果没有构造方法----- 该方法返回为Null,用默认的无参构造
后置处理器
- bean 工厂的后置处理器 BeanDefinitionRegistryPostProcessor
① 首先执行程序员通过API提供的 ac.addBeanFactoryPostProcessor(new LuBanFactoryPostprocessor());
② 然后执行spring内置的----- 程序员提供的---- 有特点的 impl PriorityOrdered.class
③ 再执行程序员提供的 — 没有任何特点的 X impl BeanDefinitionRegistryPostProcessor ---- postProcessBeanDefinitionRegistry() - bean 的后置处理器
① 执行的是 X impl BeanDefinitionRegistryPostProcessor postProcessBeanFactory()
② 执行的是 BeanFactoryPostProcessor postProcessBeanFactory()
CGLib
Spring循环依赖
spring可以解决循环依赖的条件: 单例 并且是 setter 注入
- 推断构造方法
- 实例化一个对象
- 属性注入
- 声明周期回调初始化方法
- aop代理
- 三级缓存
① singletonObject cache1
② singletonFactories cache2
③ earlySingletonObjects cache3
Bean的后置处理器 | 置入位置 |
---|---|
0 = {ApplicationContextAwareProcessor@1878} | refresh() ->prepareBeanFactory()-> beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)) |
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1879} | |
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1880} | refresh() -> registerBeanPostProcessors(beanFactory)()-> registerBeanPostProcessors-> beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)) |
3 = {CommonAnnotationBeanPostProcessor@1881} | |
4 = {AutowiredAnnotationBeanPostProcessor@1882} | @EnableAspectJAutoProxy ->@Import(AspectJAutoProxyRegistrar.class) -> registerOrEscalateApcAsRequiredAopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry) |
5 = {RequiredAnnotationBeanPostProcessor@1883} | |
6 = {ApplicationListenerDetector@1884} | refresh() ->prepareBeanFactory()-> beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)) |
Spring AOP
- aspect 切面
- Join point 连接点,aop-代理— 增强对象\类— 一个方法
- advice 通知
- pointCut 切入点 — 某一类型连接点的集合
- target 目标对象
- proxy 代理对象
- weaving 织入
- bean 的生命周期 bd -> class -> object -> bean
- 判断当前Bean 是不是需要被代理
- 拿到这个类,判断这个类是否满足@PointCut 指定的表达式
构造方法推断 与注入的模型有关
- 手动装配,默认@AutoWired
① 提供两个有效的,异常 构造方法上加 @AutoWired 指定使用这个构造方法实例化
② 提供1个,不是有效的,就会推断出来
③ 提供多个构造(包括无参的),默认使用无参的
④ 提供多个构造(不包括无参的),异常:ested exception is java.lang.NoSuchMethodException: com.zfx.service.OrderService. - 自动装配: mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
① 全部拿出来,推断使用哪一个构造