Spring面试题(三)

目录

目录

十二、静态代理和动态代理的区别(A)

十三、Spring 怎么使用动态代理(A)

十四、Spring框架中的Bean的作用域(A)

十五、Spring 框架中的Bean的线程安全

十六、Spring 框架中的Bean生命周期(A)

十七、Spring 框架如何解决循环依赖?(A)

十八、Spring 框架中有哪些注解?(A)

十九、Spring 框架中用到的设计模式(A)

二十、Spring 框架中AOP的基本理解(A)

二十一、Spring AOP 和 AspectJ AOP 有什么区别?(A)


十二、静态代理和动态代理的区别(A)

1.实现方式

  • 静态代理需手动编写代理类,在程序运行前存在。
  • 动态代理在程序运行时动态生成,有基于接口的 JDK 动态代理和基于类的 CGLIB 动态代理。

2.灵活性

  • 态代理灵活性,接口变化需改代码且功能相对固定。
  • 态代理灵活性,可根据不同条件在运行时调整。

3.性能:

  • 静态代理性能较好,无动态生成开销。
  • 动态代理有一定性能开销,CGLIB 动态代理性能通常比 JDK 动态代理好一些。

十三、Spring 怎么使用动态代理(A)

Spring AOP 基于动态代理实现:

  • 如果被代理的对象,已经实现某个接口,则SpringAOP会使用JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和 Proxy);
  • 如果被代理的对象,没有实现某个接口,就无法使用JDK Proxy去进行代理了,这时候Spring AOP 会使用Cglib基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是 MethodInterceptor接口和Enhancer);
  • (Spring Aop是运行时增强)

十四、Spring框架中的Bean的作用域(A)

  1. singleton: Spring 只会为该 bean 对象只会创建唯一实例,Spring 中的bean默认都是单例;
  2. prototype :每次获取 bean,Spring 会创建一个新的bean 实例;
  3. request: 每一次 HTTP 请求,Spring 会创建一个新的bean 实例;
  4. session : 不同的 HTTP 会话,Spring 会创建不同的bean 实例;
通过XML方式设置bean的作用域

<bean id="demoDaoBean" class="com.apesource.dao.DemoDA0Impl" scope="singleton"/>
通过注解方式设置bean的作用域

@Scope(ConfigurableBeanFactory.SCOPE PROTOTYPE)

public class DemoDA0Impl implements IDemoDA0{ }

十五、Spring 框架中的Bean的线程安全

       1.对于prototype作用域的 Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。

       2.对于 singleton 作用域的 Bean,所有的线程都共享一个单例状态的 Bean,存在资源竞争,因此是存在线程安全问题的。

3.解决办法:

对于 singleton 作用域的单例 bean,它的线程安全问题,常见有两种解决办法:

  1. 在 bean 中尽量避免定义可变的成员变量(用于保存数据的成员变量)
  2. 在类中定义一个 ThreadLocal 成员变量,将需要可变的成员变量保存在ThreadLocal中

十六Spring 框架中的Bean生命周期(A)

1. Spring Bean 的生命周期总体分四个阶段: 实例化=>属性注入 =>初始化 =>销毁

Step1 实例化 Bean:根据配置文件中 Bean 的定义,利用 Java Reflection 反射技术创建 Bean 的实例

Step2 注入对象依赖的属性值(或对象)

Step3 处理各种Aware接口: Spring 会检测该 Bean 是否实现了 xxxAware 接口,通过 Aware 类型的接口,可以让Spring框架为当前 Bean 注入相应的内容

  1. 如果 Bean 实现 BeanNameAware 接口,会调用它实现的 setBeanName(string beanId)方法,注入 Bean 的名字;
  2. 如果 Bean 实现 BeanclassLoaderAware 接口,调用 setBeanclassLoader()方法,注入lassLoader 对象的实例;
  3. 如果 Bean 实现 BeanFactoryAware 接口,会调用它实现的 setBeanFactory()方法,注入的是 Spring 工厂;
  4. 如果 Bean 实现 ApplicationContextAware 接口,会调用 setApplicationContext()方法,注入 Spring 上下文;

Step4 执行BeanPostProcessor前置处理:如果想对 Bean 进行一些自定义的前置处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,将会在该阶段调用 postProcessBeforeInitialization(object obj,string s)方法。

Step5 执行InitializingBean初始化方法:如果 Bean 实现了 InitializingBean 接口,执行afeterPropertiesset()方法。

Step6 执行init-method自定义初始化方法:如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

Step7 执行BeanPostProcessor后置处理:如果这个 Bean 实现了BeanPostProcessor接口,将会调用 postProcessAfterInitialization(0biect obi,string s)方法,由干这个方法是在 Bean 初始化结束后调用;

以上几个步骤完成后,已经被正确创建,可以正常使用这Bean了

Step8 执行DisposableBean销毁Bean:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy()方法执行销毁;

Step9 执行destroy-method自定义销毁方法: 如果这个 Bean 的 spring 配置中配置了 destroy-method 属性,会自动调用其配置的自定义销毁方法。

十七、Spring 框架如何解决循环依赖?(A)

       循环依赖问题是指:类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。        

        例如: A类依赖了B类,B类依赖了C类,而最后C类又依赖了A类,这样就形成了循环依赖问题;

解决:Spring 框架解决循环依赖主要通过三级缓存来实现。

 

三级缓存分别是

  1. 一级缓存:singletonObjects,用于存放完全创建好的单例 Bean 实例。
  2. 二级缓存:earlySingletonObjects,存放早期暴露的 Bean 实例(未完成属性注入)。
  3. 三级缓存:singletonFactories,存放可以生成早期 Bean 实例的工厂对象。

解决过程如下
        当创建一个 Bean 时,首先会在一级缓存中查找,如果未找到则开始创建。在创建过程中,如果发现存在循环依赖,会尝试从二级缓存和三级缓存中获取早期的 Bean 实例或者通过工厂对象来创建早期实例以解决依赖。

        例如,有 A 和 B 两个 Bean 相互依赖。当创建 A 时,发现需要 B,此时 B 还未完全创建好,但是其早期实例或者工厂对象可能已经在二级或三级缓存中,从而能够满足 A 的依赖,解决循环依赖问题。

        通过这种方式,Spring 框架有效地处理了循环依赖的情况,保证了 Bean 的正常创建和依赖注入。

十八、Spring 框架中有哪些注解?(A)

1.用于声明 Bean 的注解:

     @Component:定义通用Bean的注解,可标注任意类为 Bean 。如果一个 Bean 不知道属于哪个层,可以使用 @component 注解标注。

       @Repository:定义数据访问层Bean的注解

       @service:定义业务层Bean的注解

       @Controller:定义控制器Bean的注解用于注入的注解;

2.按类型自动注入:

       @Autowired:按类型自动创建

       @Qualifier:按名称自动注入

              声明配置、扫描、启用特性的注解;

       @Configuration:声明配置类

       @Componentscan:组件扫描

       @EnableScheduling :启用任务调度

       @EnableAspectJAutoProxy:启用自动代理工厂

十九、Spring 框架中用到的设计模式(A)

       1.·工厂模式:Spring 使用工厂模式,通过 BeanFactoryApplicationcontext 来创建对象

       2.单例模式:Bean 默认作用域为单例,按照单例设计模式进行设计实现;

       3.策略模式:Resource 的实现类,针对不同的资源文件,实现了不同方式的资源获取策略;

       4.代理模式:SpringAOP 的实现依靠动态代理(JDK的反射和CGLIB)

       5.模板方法:Spring 提供了 JdbcTemplateRedisTemplate 等模板对象,将相同的操作步骤进行了封装;

       6.适配器模式:Spring A0P 的增强或通知(Advice)使用到了适配器模式,Spring MVC中也用到了适配器模式适配 Controller;

二十、Spring 框架中AOP的基本理解(A)

记忆关键字:AOP名词解释,AOP实现原理(动态代理)

1.A0P(Aspect-0riented Programming:面向切面编程):(定义)将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”( Aspect );(优点)便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

2.Spring AOP 基于动态代理实现:

  • 如果被代理的对象,已经实现某个接口,则SpringAOP会使用JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和 Proxy);
  • 如果被代理的对象,没有实现某个接口,就无法使用JDK Proxy去进行代理了,这时候Spring AOP 会使用Cglib基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是 MethodInterceptor接口和Enhancer);

二十一、Spring AOP 和 AspectJ AOP 有什么区别?(A)

关键字:增强方式的差异(运行时、编译时),实现方式的差异(动态代理、字节码操作)

       1.SpringAOP已经集成了AspectJAspectJ是一个Java 技术生态系统中实现 AOP 编程思想的独立框架; AspectJ相比于SpringAOP功能更加强大,但是 SpringAOP相对来说更简单更容易;

       2.SpringAOP属于运行时增强,而 AspectJ编译时增强;

    3.SpringAOP基于动态代理(Proxying),而AspectJ基于字节码操作( Bytecode Manipulation );

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷酷无情小美

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值