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会触发事务回滚。