Spring相关知识点

https://blog.csdn.net/a745233700/article/details/80959716

https://thinkwon.blog.csdn.net/article/details/104397516

1、是什么是IOC?

控制反转把创建对象的权利交给工厂或者框架,在原来,我们获取对象是采用new的方式,是主动的,现在我们获取对象时,是向工厂或者框架容器要的,有工厂或者框架容器帮我们查找或创建对象,是被动的。这种被动接受的方式获取对象的思想就是控制反转。

2、Spring创建bean的三种方式
  1. 通过默认构造函数创建
  2. 通过spring管理静态工厂,使用静态工厂的方法来创建对象
    class:静态工厂的全限定类名
    factory-method:静态工厂获取对象的静态方法
  3. 通过spring管理实例工厂,使用实例工厂的方法来创建对象
    factory-bean: 实例工厂的id
    factory-method: 实例工厂获取对象的方法
3、什么是依赖注入?

依赖注入是spring ioc的具体实现,我们在编写程序时,通过控制反转,把对象的创建交给spring,spring ioc是降低程序间的依赖关系,而不能消除依赖关系,像这种依赖关系,在使用spring之后,就由spring来维护。

例如:我们的业务层调用持久层的方法,spring为我们提供持久层的对象,我们只需要在配置文件描述即可,依赖关系的维护就称为依赖注入。依赖注入的本质就是装配,装配是依赖注入的具体行为。

能注入的数据类型大致分为三类

  1. 基本数据类型和String
  2. 其他bean(在ioc容器的bean)
  3. 复杂类型/集合类型

依赖注入的三种方式

  1. 构造函数注入
  2. set方法注入
  3. 接口注入
4、什么是AOP?

AOP即Aspect Oriented Program,面向切面编程,是面向对象编程(OOP)的一种增强模式,可以将项目中与业务无关的,却为业务模块所共同调用的非核心代码封装成(比如事务管理、日志管理、权限控制等等)一个个切面,然后在运行的时候通过动态代理或者CGLib代理的方式织入到核心业务功能中。

5、Spring自动装配Bean的二种方式

5.1 基于xml的自动装配
Spring容器可以在不使用<constructor-arg><property>元素的情况下自动装配相互协作的bean之间的关系,助于减少编写一个大的基于Spring的应用程序的XML配置的数量使用元素的autowire属性为一个bean定义指定自动装配模式。

在Spring中,我们有4种方式可以装配Bean的属性。

  1. byName
    通过byName方式自动装配属性时,是在定义Bean的时候,在property标签中设置autowire属性为byName,那么Spring会自动寻找一个与该属性名称相同或id相同的Bean,注入进来。

  2. byType
    通过byType方式自动注入属性时,是在定义Bean的时候,在property标签中设置autowire属性为byType,那么Spring会自动寻找一个与该属性类型相同的Bean,注入进来。

  3. constructor
    通过构造器自动注入。在定义Bean时,在bean标签中,设置autowire属性为constructor,那么,Spring会寻找与该Bean的构造函数各个参数类型相匹配的Bean,通过构造函数注入进来。

  4. autodetect
    自动装配。如果想进行自动装配,但不知道使用哪种类型的自动装配,那么就可以使用autodetect,让容器自己决定。这是通过在定义Bean时,设置bean标签的autowire属性为autodetect来实现的。设置为autodetect时,Spring容器会首先尝试构造器注入,然后尝试按类型注入。

默认情况下,Spring是不进行自动装配的。我们可以在xml中,设置beans标签的default-autowire属性为byName,byType等,来设置所有bean都进行自动装配。

5.2基于注解的自动装配
使用@Autowired、@Resource

5.3基于java配置装配
。。。


6、Spring常用注解

@Component

作用:把资源让spring来管理,相当于在xml中配置一个bean
属性:value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。

@Controller、@Service、@Repository

他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。
@Controller:一般用于表现层的注解。
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。
细节:如果注解中有且只有一个属性要赋值时,且名称是 value,value 在赋值是可以不写。

@Autowired

作用:自动按照类型注入。当使用注解注入属性时,set方法可以省略,它只能注入其他bean类型,当该类型有多个对象进行匹配时,使用要注入的对象变量名称作为bean的id在spring容器中查找,找到了也可以注入成功,找不到就报错。

@Qualifier

作用:在按照自动类型注入的基础上,再按照bean的id注入,它在给字段注入时不能单独使用,必须和@Autowired一起使用,但是在给方法参数注入时,可以单独使用。
属性:value:指定 bean 的 id。
@Qualifier的value默认为"" 所以必须指定value,否则报错,找不到该类型的bean

@Primary

注解@Primary代表首要的,当Spring IoC通过一个接口或者抽象类注入对象的时候,由于存在多个实现类或 者具体类,就会犯糊涂,不知道采用哪个类注入为好。注解@Primary则是告诉Spring IoC容器,请优先使用该类注入。

@Resource

如果指定name,则按bean的id查找,找不到报错;
如果指定type,则按类型查找,找不到报错;
如果指定了name和type,则按两者的交集查找,找不到报错;
如果不指定,则将属性名称作为beanId,先按bean的id查找,找不到则通过类型查找,找不到就报错。

@Value

作用:注入基本数据类型和String类型
属性:value用于指定值

@Scope

作用:指定bean的作用范围
属性:value指定范围的值:singleton、prototype、request、session、global session

@PostConstruct

作用:用于指定初始化方法-----与bean的生命周期有关

@PreDestroy

作用:用于指定销毁方法-----与bean的生命周期有关

@Configuration

作用:用于指定当前类是spring的配置类,当创建容器时,会从该类上加载注解。获取容器时,需要使用AnnotationConfigApplicationContext(有@Configuration注解的类.class)
属性:value:指定配置的id

@ComponentScan

作用:用于指定spring在初始化容器要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。
属性:basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。

@Bean

作用:该注解只能使用在方法上,表示使用此方法创建一个对象,并放入spring容器中。
属性:name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
如果不指定name属性,则@Bean注解标注的方法名为bean的id

@PropertySource

作用:用于加载.properties文件中的配置,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:

@Import

作用:用于引入其他配置类,在引入其他配置类时,其他配置类可以不用再写@Configuration 注解。当然,写上也没问题。
属性:value[]:用于指定其他配置类的字节码。

@Required

作用:@Required 注解应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。

@Condition注解的作用

public class TulingCondition implements Condition {
    /**
    * 当条件满足时,被@Condition注解标记的类才会被spring处理
    * @param context
    * @param metadata
    * @return true:加载  false:不加载
    */
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //判断容器中是否有tulingAspect的组件
        if(context.getBeanFactory().containsBean("tulingAspect")) {
        	return true;
        }
        return false;
	}
}
public class MainConfig {
    @Bean
    public TulingAspect tulingAspect() {
    	return new TulingAspect();
    }
    //当切 容器中有tulingAspect的组件,那么tulingLog才会被实例化.
    @Bean
    @Conditional(value = TulingCondition.class)
    public TulingLog tulingLog() {
    	return new TulingLog();
    }
}

在这里插入图片描述

7、Spring的通知的类型

xml-aop事务通知的执行顺序(从上到下):

  • before:前置通知
  • after-returning:返回通知(返回通知和异常通知只有一个会被执行)
  • after-throwing:异常通知(返回通知和异常通知只有一个会被执行)
  • after:最终通知(用于释放资源,无论是否发生异常都会执行)

注解-aop事务通知的执行顺序(从上到下):

  • @Before:前置通知
  • @After:后置通知
  • @AfterReturning:返回通知(返回通知和异常通知只有一个会被执行)
  • @AfterThrowing:异常通知

采用注解的方式,after-returning和after的职责发生了对调。

aop通知的执行顺序:
https://blog.csdn.net/Scoful/article/details/110405493

AOP中连接点、切点、切面的详解:
https://www.cnblogs.com/sandea/p/11175834.html

8、@Transaction失效情况
  1. Spring AOP技术使用的是动态代理,意味着,静态(static)方法和非public方法,注解@Transactional是失效。
  2. 自调用。
    由于@Transactional的实现原理是AOP,而AOP的实现原理是动态代理,而自己调用自己的过程,并不存在代理对象的调用,这样就不会产生AOP去为我们设置@Transactional配置的参数,这样就出现了自调用注解失效的问题。
  3. 类没有被spring托管
  4. 异常被捕获,未抛出
  5. 没有配置spring的事务管理器
  6. 事务的传播行为不支持事务运行
  7. 数据库本身不支持事务
  8. rollbackFor回滚异常设置不正确

public可重写可被代理(在实现类中重写是强制的)
private和static不能够被重写也不能够被代理
default可重写可代理(在实现类中不强制必须重写,不过不论重写不重写都会主动被代理)

9、Spring事务传播行为

https://blog.csdn.net/Linging_24/article/details/121726188?spm=1001.2014.3001.5501

10、Spring ioc原理:

主要步骤:

  1. 准备spring的上下文环境,applicationContext
  2. 解析配置文件,扫描所有注解,生成BeanDefinition
  3. 对bean进行实例化和初始化
  4. 把bean放到ioc容器中

详细解析:

  1. 初始化IOC容器 DefaultListableBeanFactory
  2. 读取xml配置文件
  3. 解析配置文件内容注册为BeanDefinition
  4. 执行BeanFactoryPostProcessor实现类(扩展点)
  5. 实例化(反射)(根据BeanDefinition实例化Bean)
  6. 初始化(不是java对象的初始化,是对spring参数的初始化)
    6.1 属性填充
    6.2 调用Aware结尾接口的方法
    6.3 执行postProcessBeforeInitialization方法(扩展点,前置处理,BeanPostProcessor)
    6.4 执行@PostConstruct初始化
    6.5 检查是否实现InitializingBean接口,以此来调用afterPropertiesSet方法
    6.6 执行init-method指定的方法
    6.7 执行postProcessAfterInitialization方法(扩展点,后置处理,BeanPostProcessor),aop代理对象的创建在这一步生成
  7. 完整对象,可以使用
  8. 关闭容器前
  9. 执行@PreDestory
  10. 检查是否实现DisposableBean接口
  11. 调用destory-method指定的方法
  12. 容器关闭

步骤4:执行BeanFactoryPostProcessor实现类(扩展点),后置处理器,可以在bean实例化之前对BeanDefinition进行修改,读取BeanDefinition并修改它。例如:可以进行元数据的配置,对xml文件中配置的数据源中的${jdbc.driverName}等进行值的替换。

步骤5:使用反射实例化对象

Constructor ctor = clazz.getDeclareConstructor();
Object obj = ctor.newInstance();

5.1 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。 

5.2 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。 容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。 实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。

步骤6:初始化

6.1 属性填充:实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。紧接着,Spring根据BeanDefinition中的信息进行依赖注入。并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

6.2 调用Aware结尾接口的方法:实现以Aware结尾的接口的Bean在实例化之后,可以取得一些相应的资源。例如:1.实现BeanFactoryAware接口的Bean可以在实例化之后取得BeanFactory对象;2.实现ApplicationContextAware接口的Bean在实例化之后可以取得ApplicationContext对象

6.3 和 6.7 所提供的扩展点,它们是BeanPostProcessor接口的两个方法,此时的Bean对象已经被正确的构造,如果此时想要对Bean对象进行一些自定义的处理,就可以实现BeanPostProcessor接口。(处理Bean)

  • postProcessBeforeInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会先于InitialzationBean执行,因此称为前置处理。
    所有Aware接口的注入就是在这一步完成的。
  • postProcessAfterInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会在InitialzationBean完成后执行,因此称为后置处理。

实现BeanPostProcessor接口可以实现AOP功能。

6.5 检查是否实现InitializingBean接口,以此来调用afterPropertiesSet方法

bean创建完成,所有属性注入完成后执行

当BeanPostProcessor的前置处理完成后就会进入本阶段。

InitializingBean接口只有一个函数:

  • afterPropertiesSet()

这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。

若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。

当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。

步骤8和步骤9和步骤10

和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。

spring的Bean生命周期

上述的步骤5,6,7,8,9,10,11就是Bean的生命周期
https://www.cnblogs.com/javazhiyin/p/10905294.html
在这里插入图片描述

11、Spring循环依赖
DefaultSingletonBeanRegistry类:
解决循环依赖所需要的三级缓存
// 一级缓存,保存完成的对象 Map<beanName,完成对象(代理对象)>
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of early singleton objects: bean name to bean instance. */
// 二级缓存,保存半成品对象 Map<BeanName,半成品对象> 临时 
//这个半成品对象就是实例化的,但是没有初始化的bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 三级缓存 Map<BeanName, lambda>  临时
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
bean的创建过程及循环依赖的解决:
1.遍历实例化对象
2.getBean()
3.doGetBean()
4.从容器中获取对象getSingleton(beanName)
	4.1 从一级缓存中获取对象
	4.2 从二级缓存中获取对象
	4.3 如果提前暴露对象,从三级缓存中获取lambda表达式,获取提前暴露的对象,添加到二级缓存中
	4.4 获取到对象则return;
5.容器中不存在对象,则getSington(beanName,()->{createBean()}) 
	5.1 从一级缓存中获取对象,存在则return;
	5.2 不存在则调用getObject(),即createBean()->doCreateBean()创建对象
	5.3 并加入一级缓存,移除二、三级缓存(结束)
	5.4 return 对象;
6.doCreateBean()
	6.1 实例化对象,clazz.newInstant()
	6.2 提前暴露对象,三级缓存保存()->{getEarlyBeanReference(对象)}
	6.3 移除二级缓存
	6.4 属性填充populateBean()
7.populateBean()属性填充
	7.1 遍历属性列表
	7.2 根据bean名,从容器中获取对象getBean(),步骤2
	7.3 获取到对象,则进行属性设置

思考:

0.依赖注入的属性对象是代理对象:
   如果不存在循环依赖,则代理对象在beanPostProcessor的后置处理方法中生成
   如果存在循环依赖,则代理对象会在三级缓存的ObjectFactory中提前生成,并注入
   所以三级缓存的作用是解决在循环依赖下,属性是代理对象的情况。

1.如果没有aop,解决循环依赖,只需要二级缓存即可
2.如果有aop,需要三级缓存,三级缓存解决aop时的Bean的循环依赖问题,我们的Bean是单例,通过BeanName获取的对象只能有一个,aop会生成代理对象,这时就存在代理对象和目标对象两个对象,所以就要用代理对象替代目标对象,这个过程在三级缓存的lambda表达式调用的方法中实现。

1、干掉原来的三级缓存
分析:一级缓存存放已经完成的bean,二级缓存存放已经实例化,但是还没属性注入的bean,这样会导致什么结果呢?无法处理具有AOP性质的循环依赖。
原因:我们从上面的代码中能看到,bean的AOP增强发生的初始化的after处理中和原本三级缓存获取提前引用的地方,如果我们把原来的三级缓存干掉,那么注入的就是原始的bean,无法注入有AOP增强的bean。

2、干掉原来的二级缓存
分析:上面说了必须满足可以实现有AOP增强的Bean的循环依赖注入,那么干脆就留下原来的一级缓存和三级缓存,那这样会有什么后果呢?无法处理多级依赖,举个栗子:A=>B B=>(A,C) C=>A
原因:在B中注入A的时候会调用getObject方法返回代理对象,在C中注入A的时候又会调用getObject方法返回代理对象,这样导致B和C中得到的A的注入不一致,这样显然是不行的,在中间再加一层缓存就可以轻松实现。
如果移除二级缓存,每次从三级缓存中获取,如果对象存在代理的话,会导致对象被重复代理多次。
12、spring中接口的概念
  • BeanDefinition:用于描述Spring Bean的配置信息。

  • BeanDefinitionRegistry:是BeanDefinition容器,所有的Bean配置解析后生成的BeanDefinition对象都会注册到BeanDefinitionRegistry对象中。
    Spring提供了扩展机制,允许用户在Spring框架启动时,动态地往BeanDefinitionRegistry容器中注册BeanDefinition对象。

  • BeanFactory:是Spring的Bean工厂,负责Bean的创建及属性注入。它同时是一个Bean容器,Spring框架启动后,会根据BeanDefinition对象创建Bean实例,所有的单例Bean都会注册到BeanFactory容器中。

  • BeanFactoryPostProcessor:是Spring提供的扩展机制,用于在所有的Bean配置信息解析完成后修改Bean工厂信息。postProcessBeanFactory

  • ImportBeanDefinitionRegistrar:是一个接口,该接口的实现类作用于Spring解析Bean的配置阶段,
    当解析@Configuration注解时,可以通过ImportBeanDefinitionRegistrar接口的实现类向BeanDefinitionRegistry容器中添加额外的BeanDefinition对象。

  • BeanPostProcessor:Bean的后置处理器,在Bean初始化方法(init-method属性指定的方法或afterPropertiesSet()方法)调用前后,会执行BeanPostProcessor中定义的拦截逻辑。

  • ClassPathBeanDefinitionScanner:是BeanDefinition扫描器,能够对指定包下的Class进行扫描,将Class信息转换为BeanDefinition对象注册到BeanDefinitionRegistry容器中。

  • FactoryBean:是Spring中的工厂Bean,通常用于处理Spring中配置较为复杂或者由动态代理生成的Bean实例。实现了该接口的Bean不能作为普通的Bean使用,而是作为单个对象的工厂。
    当我们通过Bean名称获取FactoryBean实例时,获取到的并不是FactoryBean对象本身,而是FactoryBean对象的getObject()方法返回的实例。提供自定义bean实例化的逻辑。

  • InitializingBean:实现此接口的Bean会在初始化时调用其afterPropertiesSet方法来进行bean的逻辑初始化。

  • ApplicationContextAware:Spring在创建该Bean时会调用setapplicationContext方法注入上下文

  • BeanNameAware:创建是调用setBeanName方法

  • DisposableBean:DisposableBean接口和InitializingBean接口一样,为bean提供了释放资源方法的方式,它只包括destroy方法,凡是继承该接口的类,在bean被销毁之前都会执行destory()方法。

  • BeanDefinitionRegisterPostProcessor
    这个接口继承了BeanFactoryPostProcessor. 从名字上来看, 这个接口是BeanDefinitionRegistry的后处理器,

    我们先介绍下BeanDefinitionRegistry.
    
    BeanDefinitionRegistry是用来注册BeanDefinition的.
    
    BeanDefinition就是Bean的配置元数据或Bean的描述信息, 比如Bean的属性值, 构造方法的参数值等. 上面的BeanFactory的BeanDefinition也是由它注册的.
    
    BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展, 允许在BeanFactoryPostProcessor被调用之前对BeanDefinition做一些操作, 尤其是它可以注册BeanFactoryPostProcessor的BeanDefinition.
    
    它提供了一个方法postProcessBeanDefinitionRegistry(), 这个方法被调用的时候, 所有的BeanDefinition已经被加载了, 但是所有的Bean还没被创建.
    
    注意: 
    所有的Bean生成都有个顺序: 定义 --> 创建 --> 初始化.
    BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry和postProcessBeanFactory方法在Bean被定义但还没被创建的时候执行.
    
  • 执行顺序:加载顺序为PriorityOrdered -> Ordered -> 都没实现

  • MergedBeanDefinitionPostProcessor

  • ApplicationListener

ApplicationListener可以监听某个事件event

通过实现这个接口,传入一个泛型事件,在run方法中就可以监听这个事件,从而做出一定的逻辑

比如在等所有bean加载完之后执行某些操作

public class SystemListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) {
            System.out.println("do something");
        }
    }
}

Spring内置事件
1、ContextRefreshedEvent
ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用

2、ContextStartedEvent
当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序

3、ContextStoppedEvent
当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作

4、ContextClosedEvent
当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

5、RequestHandledEvent
这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件

6、自定义监听器,继承ApplicationEvent
13、spring加载类到ioc容器中,有哪些方式?
  1. @Import(xxx.class)
  2. @Import(MyImportSelector.class)
  3. @Import({MyImportBeanDefinitionRegistrar.class})
  4. @Bean导入
  5. @ComponentScan 注意:使用时扫描其他包路径时,当前包扫描路径也得加上
  6. 实现Factory接口
  7. 在resource下创建META-INF/spring.factories,其中编写org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx
14、spring中使用了哪些设计模式
  • 工厂模式:Spring使用工厂模式通过BeanFactory、ApplicationContext创建bean对象。
  • 代理模式:Spring Aop功能
  • 单例模式:Spring中的Bean默认是单例
  • 模板方法:Spring中jdbcTemplate、hibernateTemplate等以Template结尾的对象数据库操作的类,它们就使用到了模板方法
  • 策略模式:项目连接多个数据库,根据不同需要访问不同数据库。
  • 观察者模式:Spring事件驱动模型就是典型的观察者模式的应用
  • 适配器模式:Spring Aop的增强或通知(Advice)使用到了适配器模式,SpringMVC中也使用了适配器模式适配Controller。
15、spring对循环依赖的处理有三种情况:
  1. 构造器的循环依赖:这种依赖spring是处理不了的,直接排除BeanCurrentlyInCreationException异常。
  2. 单例模式下的setter循环依赖:通过三级缓存处理循环依赖
  3. 非单例循环依赖:无法处理
16、spring事务传播行为及this失效详解

spring事务传播行为及this失效详解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值