第三讲、Spring之bean生命周期

文章内容根据黑马程序员Spring视频教程所写!!!

视频地址:点击这里


Spring Bean生命周期的各个阶段

生命周期的执行顺序

/**
 * @author Becant
 * 2024-04-25-17:52
 * @version 1.0.0
 * bean生命周期
 */
@SpringBootApplication
public class A03Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
        context.close();
    }
}
@Component
public class LifeCycleBean {

    private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);

    public LifeCycleBean() {
        log.info("构造");
    }

    // 说明:@Autowired不会注入String类型的bean,如果有@Value修饰,则会以值注入的方式注入bean
    @Autowired
    public void autowired(@Value("${JAVA_HOME}") String home) {
        log.info("依赖注入:{}", home);
    }

    // 注解作用:初始化
    @PostConstruct
    public void init() {
        log.info("初始化");
    }

    // 注解作用:销毁
    @PreDestroy
    public void destroy() {
        log.info("销毁");
    }
}

控制台打印:

执行顺序:构造方法->依赖注入->初始化->销毁。Spring bean只有这四个生命周期

生命周期的功能增强

生命周期功能增强也就是:生命周期某个阶段的执行前后要增加的功能

/**
 * @author Becant
 * 2024-04-25-18:09
 * @version 1.0.0
 * 后处理器
 */
//实现了两个Bean后处理器
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<<<<<<<<<销毁之前执行, 如@preDestroy");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<实例化之前执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<实例化之后执行, 这里返回false会跳过依赖注入阶段,返回true则不会");
//            return false;
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<依赖注入阶段执行, 扩展功能,如解析@Autowired @Resource @Value");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<初始化之前执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换 如@PostConstruct @ConfigurationProperties");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("LifeCycleBean")) {
            log.info("<<<<<<<<初始化之后执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换 如代理增强");
        }
        return bean;
    }
}

控制台打印:

模板方法

模版方法是设计模式的其中一种,使用模版方法能使代码更容易扩展。

现在有一个方法

public Object getBean() {
        Object bean = new Object();
        System.out.println("构造" + bean);
        System.out.println("依赖注入" + bean);
        System.out.println("初始化" + bean);
        return bean;
}

如果我们想在依赖注入阶段增强功能,例如增加@Autowired和@Resource的解析。如果不是用模版方法,只能在刚方法的基础上修改代码,这样就违反了开放封闭原则,对修改封闭,对扩展开放。

public Object getBean() {
        Object bean = new Object();
        System.out.println("构造" + bean);
        System.out.println("依赖注入" + bean);
    	System.out.println("解析@Autowired");
        System.out.println("解析@Resource");
        System.out.println("初始化" + bean);
        return bean;
}

如果使用模版方法

public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
        // 扩展功能
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
        beanFactory.getBean();
    }

    static class MyBeanFactory {
        public Object getBean() {
            Object bean = new Object();
            System.out.println("构造" + bean);
            System.out.println("依赖注入" + bean);
            for (BeanPostProcessor processor : processors) {
                processor.inject(bean);
            }
            System.out.println("初始化" + bean);
            return bean;
        }
        // 模版接口集合
        private List<BeanPostProcessor> processors = new ArrayList<>();
        // 增加BeanPostProcessor,扩展功能
        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
            processors.add(beanPostProcessor);
        }
    }
    // 模版接口
    static interface BeanPostProcessor {
        public void inject(Object bean);
    }
}

使用模版方法,观察getBean()方法,对于一些能确定的扩展(静态部分)保持不变;对于一些不能确定的扩展(动态部分),把它抽象成接口(或者抽象类),这个模版接口所声明的方法,是我们要自己实现的,即根据自己所需实现功能。然后在getBean()方法所在的类上添加一个管理模版接口的集合,以及add方法(把模板接口添加到集合)。在getBean()类上遍历集合,调用方法,就能实现功能。功能的扩展只需要在main函数上添加代码,而不需要修改getBean()函数。


第三讲、Spring之bean生命周期
http://example.com/2024/04/25/第三讲、Spring之bean生命周期/
发布于
2024年4月25日
更新于
2024年4月25日
许可协议