Spring相关的面试题

1、spring中bean的生命周期

spring bean的生命周期主要分为三大类 ,分别是创建-》使用-〉销毁。

在三大类下面又可以分为5个小类。分别是  实列化-〉初始化-》组册destruction回调-〉使用-〉销毁

这这其中 初始化也可以细分为 设置属性值,前置处理,后置处理 这些

1. 实例化Bean:
•Spring容器首先创建Bean实例。
 在AbstractAutowireCapableBeanFactory类中的createBeanlnstance方法中实现
2. 设置属性值:
 Spring容器注入必要的属性到Bean中。
•在AbstractAutowireCapableBeanFactory的populateBean方法中处理
3. 检查Aware:
如果Bean实现了BeanNameAware、BeanClassLoaderAware等这些Aware接口,Spring容器会调用它们。
在AbstractAutowireCapableBeanFactory的initializeBean方法中调用
4. 调用BeanPostProcessor的前置处理方法:
在Bean初始化之前,允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态。BeanPostProcessor的postProcessBeforelnitialization方法会在此时被调用。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforelnitialization方法执行。
5. 调用InitializingBean的afterPropertiesSet方法:
提供一个机会,在所有Bean属性设置完成后进行初始化操作。如果Bean实现了InitializingBean接口,afterPropertiesSet方法会被调用。
在AbstractAutowireCapableBeanFactory的invokelnitMethods方法中调用。

6. 调用自定义init-method方法:

提供一种配置方式,在XML配置中指定Bean的初始化方法。如果Bean在配置文件中定义了初始化方法,那么该方法会被调用。
在AbstractAutowireCapableBeanFactory的invokelnitMethods方法中调用。
7. 调用BeanPostProcessor的后置处理方法:
在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理。BeanPostProcessor的postProcessAfterinitialization方法会在此时被调用。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterlnitialization方法执行
8. 注册Destruction回调:
如果Bean实现了DisposableBean接口或在Bean定义中指定了自定义的销毁方法,Spring容器会为这些
Bean注册一个销毁回调,确保在容器关闭时能够正确地清理资源。
在AbstractAutowireCapableBeanFactory类中的registerDisposableBeanlfNecessary方法中实现
9.Bean准备就绪:
此时,Bean已完全初始化,可以开始处理应用程序的请求了。
10. 调用DisposableBean的destroy方法:
当容器关闭时,如果Bean实现了DisposableBean接口,destroy方法会被调用。
在DisposableBeanAdapter的destroy方法中实现
11. 调用自定义的destory-method
如果Bean在配置文件中定义了销毁方法,那么该方法会被调用。
在DisposableBeanAdapter的destroy方法中实现


可以看到,整个Bean的创建的过程都依赖于AbstractAutowireCapableBeanFactory这个类,而销毁主要依赖DisposableBeanAdapter这个类。

AbstractAutowireCapableBeanFactory 的入口处,doCreateBean的核心代码如下,其中包含了实例化、设置属性值、初始化Bean以及注册销毁回调的几个核心方法。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

        //实列化bean
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
        //。。。。。。。

        Object exposedObject = bean;

        try {
            //设置属性值
            this.populateBean(beanName, mbd, instanceWrapper);
            //初始化bean
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            Throwable ex = var18;
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)ex).getBeanName())) {
                throw (BeanCreationException)ex;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }

      //。。。。。

        try {
            //注册bean的销毁回调
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

2、使用Aop可以实现哪些功能?

2.1、通过ioc实现策略模式

很多时候,我们需要对不同的场景进行不同的业务逻辑处理,举个例子,譬如不同的场景需要不同支付方式,普通
的逻辑是使用if-else,如下所示:

public void use(String code) {
if(code .equals("weixin")) {
doWeiXinPay () ;
} else if (code .equals("alipay")) {
doAlipay();
} else {
doDothing();
}

如果code越来越多,这种if-else显然非常不合适,就需要我们借助Spring来完成策略模式

package com.hellobike.moon.api.pay;

import org.springframework.beans.factory.InitializingBean;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 马震
 * @date 2024/7/11 16:40
 */
public interface PayFacade extends InitializingBean {

    void pay();

    String getCode();

    @Override
    default void afterPropertiesSet() throws Exception{
        PayFactory.register(getCode(),this);
    };

    class WeiXinPay implements PayFacade{
        @Override
        public void pay() {
            // by WeiXin
        }

        @Override
        public String getCode() {
            return "winxin";
        }
    }

    class AliPay implements PayFacade{
        @Override
        public void pay() {
            // by AliPay
        }

        @Override
        public String getCode() {
            return "alipay";
        }
    }



    class PayFactory {
        private static final Map<String,PayFacade> payFacadeMap = new HashMap<>();
        public static void register(String scene,PayFacade payFacade){
            payFacadeMap.put(scene,payFacade);
        }
        public static PayFacade get(String scene){
            return payFacadeMap.get(scene);
        }
    }

}

这样子,调用方只需要调用PayFactory#get即可,不需要感知内部的实现细节和逻辑。
需要说明的是,这里使用了InitializingBean只是实现方式之一,还有其他的实现方式,如通过Autowired注解,
BeanPostProcess等,这里不做过多赘述。

2.2、通过Aop实现拦截

很多时候,我们一般是通过注解和AOP相结合。大概的实现思路就是先定义一个注解,然后通过AOP去发现使用过该注解的类,对该类的方法进行代理处理,增加额外的逻辑,譬如参数校验,缓存,日志打印等等,如下代码所示:

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsCheck {
    boolean ignore() default false;
}
@Aspect
@Component
@Slf4j
public class ValidateAspect {

    /**
     * 定义切点
     * @param paramsCheck
     */
    @Pointcut("@annotation(ParamsCheck)")
    public void validate(ParamsCheck paramsCheck) {
    }


    /**
     * 环绕通知
     * @param pjp
     * @param paramsCheck
     * @return
     */
    @Around("validate(paramsCheck)")
    public Object ParamsCheckAround(ProceedingJoinPoint pjp,ParamsCheck paramsCheck) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        ParamsCheck annotation = method.getAnnotation(paramsCheck.getClass());
        if(annotation != null && annotation.ignore()){
            return pjp.proceed();
        }
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            if(arg == null){
                break;
            }
            //参数校验,失败抛出异常
        }
        return null;
    }
}

根据这个思路可以做一些日志拦截,缓存逻辑等等。

3、Spring的Aop在什么场景会失效

1、私有方法调用
2、静态方法调用
3、final方法调用
4、类内部自调用
5、内部类方法调用

4、Spring事物的传播机制有哪些

Spring的事务规定了7种事务的传播级别,默认的传播机制是REQUIRED


•REQUIRED,如果不存在事务则开启一个事务,如果存在事务则加入之前的事务,总是只有一个事务在执行
•REQUIRES_NEW,每次执行新开一个事务,如果当前存在事务,则把当前事务挂起
•SUPPORTS,有事务则加入事务,没有事务则普通执行
• NOT_SUPPORTED,有事务则暂停该事务,没有则普通执行
• MANDATORY,强制有事务,没有事务则报异常
•NEVER,有事务则报异常
• NESTED,如果之前有事务,则创建嵌套事务,嵌套事务回滚不影响父事务,反之父事务影响嵌套事务

 rollbackFor
rollbackFor是Spring事务中的一个属性,用于指定哪些异常会触发事务回滚。
在一个事务方法中,如果发生了rollbackFor属性指定的异常或其子类异常,则事务会回滚。如果不指定
rollbackFor,则默认情况下只有RuntimeException和Error会触发事务回滚。

5、SpringMvc的执行流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值