三、Spring学习 : Bean---->Bean的生命周期+模版设计模式

Bean的生命周期

点击查看本节代码
public class AutowiredBeanPostProcessor {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //我们之前使用的DefaultListableBeanFactory想要加入Bean需要做一个描述类,相比大家还记得第一讲的AbstractBeanDefinition
        //要先搞一个描述,然后把描述注册到工厂,beanFactory.registerBeanDefinition();
        //我们这里用一个简单的定义方式,这种定义方式会认为你的Bean已经初始化好了
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.registerSingleton("bean3",new Bean3());
        //再来加上一个帮我们解析@Value的自动装配解析器,目前我们知道他可以帮我们解析@Value,其实功能非常强大
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //再加一个解析${}的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);


        //把AutowiredAnnotationBeanPostProcessor单拿出来,让他去作用于Bean1,如果需要找Bean2和Bean3,去beanFactory里面
        AutowiredAnnotationBeanPostProcessor BeanPostProcessor =
                new AutowiredAnnotationBeanPostProcessor();
        BeanPostProcessor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
//        System.out.println(bean1);
//        //这个Bean后处理器的方法,我们之前是不是学到过呢?在bean的生命周期的依赖注入阶段,我们使用到了的,
//        // 第一个参数是我们注入值,第二个是我们处理的Bean,第三个是我们Bean的名称
//        BeanPostProcessor.postProcessProperties(null,bean1,"bean1");
//        System.out.println(bean1);
        //我们看到第一次打印的时候Bean1什么都没有,而第二次打印则自动注入了进去


        //那么AutowiredAnnotationBeanPostProcessor到底怎么玩的呢?

        //我们先将上面的代码注释,观察底层代码,发现就是先找到加了@Autowired、@Value的成员变量和方法参数然后封装成InjectionMetadata,然后反射调用,注入值
        Method method = AutowiredAnnotationBeanPostProcessor.class
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        method.setAccessible(true);
        InjectionMetadata injectionMetadata =
                (InjectionMetadata) method.invoke(BeanPostProcessor, "bean1", Bean1.class, null);//获取加了@Autowired、@Value的成员变量和方法参数
        System.out.println(injectionMetadata);//断点调试我们看到已经解析了@Autowired、@Value的成员变量和方法参数
        injectionMetadata.inject(bean1,"bean1",null);
        System.out.println(bean1);
        //已经生效

        //1.按类型注入成员变脸时:
        //如何按照类型注入呢?
        Field field = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd = new DependencyDescriptor(field,false);//Spring底层会将field封成DependencyDescriptor依赖描述
        Object o = beanFactory.doResolveDependency(dd, null, null, null);
        System.out.println(o);
        //查看打印结果,我们发现已经找到了Bean3并创建
        //2.注入方法变量时:
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 =
                new DependencyDescriptor(new MethodParameter(setBean2,0),false);
        Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o2);
        //3.值注入的时候,相比已经形成了套路
        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor dd3 =
                new DependencyDescriptor(new MethodParameter(setHome,0),false);
        Object o3 = beanFactory.doResolveDependency(dd3, null, null, null);
        System.out.println(o3);
    }
}





package com.itvayne.springbootcloudstudy.spring_03_beanlife;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

public class Bean1 {
    private static final Logger log = LoggerFactory.getLogger(Bean1.class);
    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.debug("@Autowired 生效: {}}", bean2);
        this.bean2 = bean2;
    }

    @Autowired
    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.debug("@Resource 生效: {}}", bean3);
        this.bean3 = bean3;
    }

    private String port;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}")String port) {
        log.debug("@Value 生效: {}", port);
        this.port = port;
    }

    @PostConstruct
    public void init() {
        log.debug("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy() {
        log.debug("@PreDestroy 生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", port='" + port + '\'' +
                '}';
    }
}

public class Bean2 {
}

public class Bean3 {
}

@Component
@ConfigurationProperties(prefix = "java.beanlife")
@PropertySource("classpath:/application.properties")
public class Bean4 {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Bean4{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}








public class BeanPostProcessor {
    public static void main(String[] args) {

        //准备一个比较干净的容器
        GenericApplicationContext ctx = new GenericApplicationContext();
        ctx.registerBean("bean1", Bean1.class);
        ctx.registerBean("bean2", Bean2.class);
        ctx.registerBean("bean3", Bean3.class);
        ctx.registerBean("bean4", Bean4.class);

        //换一个自动装配候选者解析器,这个后面会详细学习,默认的解析器解析不了String类型
        ctx.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        ctx.registerBean(AutowiredAnnotationBeanPostProcessor.class);//@Autowired、@Value 注解的处理器
        ctx.registerBean(CommonAnnotationBeanPostProcessor.class);//@Resource @PostConstruct @PreDestroy
        //现在运行之后会发现@Autowired、@Value都找到了

        ConfigurationPropertiesBindingPostProcessor.register(ctx.getDefaultListableBeanFactory());

        ctx.refresh();
        System.out.println(ctx.getBean(Bean4.class));
        ctx.close();
    }
}


@SpringBootApplication
public class LifeApplication {
    public static void main(String[] args) throws InterruptedException {

        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringBootCloudStudyApplication.class, args);

        applicationContext.close();


    }
}

@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.debug("beanName = " + beanName + "<<<<postProcessBeforeDestruction <<<<销毁前");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + " <<<<postProcessBeforeInstantiation<<<<Bean实例化之前,返回的结果如果不是null,会替换掉原来的Bean");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + " <<<<postProcessAfterInstantiation<<<<Bean实例化之后,返回的是false的话,会直接跳过依赖注入的阶段");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessProperties <<<<依赖注入阶段,比如@Autowired,@Resource,@Value");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessBeforeInitialization <<<<初始化之前,@PostConstruct,@ConfigurationProperty");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessAfterInitialization <<<<初始化之后,代理增强");
        }
        return bean;
    }
}


public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory myBeanFactory = new MyBeanFactory();
//        myBeanFactory.addBeanPostProcessor(bean -> {
//            System.out.println("扩展依赖注入功能");
//            return null;
//        });
        myBeanFactory.getBean();
    }

    static class MyBeanFactory {
        public Object getBean() {
            Object object = new Object();
            System.out.println("构造:" + object);
            System.out.println("依赖注入:" + object);//此时我们认为依赖注入的扩展性可能会很大
            for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                beanPostProcessor.inject(object);
            }
            System.out.println("初始化:" + object);
            return object;
        }

        private List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
            beanPostProcessors.add(beanPostProcessor);
        }
    }

    static interface BeanPostProcessor {
        public Object inject(Object bean);
    }
}

###SpringBean生命周期各个阶段

先说结论:

构造 -> 依赖注入-> 初始化方法 -> 容器关闭时,触发销毁方法(单例Bean)

Bean的后处理器提供了Bean的生命周期各个阶段的一个扩展,那么目前有哪些Bean后处理器呢?

先来看两个接口中的后处理器:

InstantiationAwareBeanPostProcessor和DestructionAwareBeanPostProcessor

package com.itvayne.springbootcloudstudy.spring_03_beanlife;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;


@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.debug("beanName = " + beanName + "<<<<postProcessBeforeDestruction <<<<销毁前");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + " <<<<postProcessBeforeInstantiation<<<<Bean实例化之前,返回的结果如果不是null,会替换掉原来的Bean");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + " <<<<postProcessAfterInstantiation<<<<Bean实例化之后,返回的是false的话,会直接跳过依赖注入的阶段");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessProperties <<<<依赖注入阶段,比如@Autowired,@Resource,@Value");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessBeforeInitialization <<<<初始化之前,@PostConstruct,@ConfigurationProperty");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("beanName = " + beanName + "<<<<postProcessAfterInitialization <<<<初始化之后,代理增强");
        }
        return bean;
    }
}

结合SpringBean的四个生命周期,我们比较典型的后处理器就是上面的六种

模版设计模式

package com.itvayne.springbootcloudstudy.spring_03_beanlife;

import org.springframework.beans.BeansException;

import java.util.ArrayList;
import java.util.List;

/**
 * @program: cloud
 * @description:
 * @author: Vayne
 * @create: 2023-12-07
 **/
public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory myBeanFactory = new MyBeanFactory();
//        myBeanFactory.addBeanPostProcessor(bean -> {
//            System.out.println("扩展依赖注入功能");
//            return null;
//        });
        myBeanFactory.getBean();
    }

    static class MyBeanFactory {
        public Object getBean() {
            Object object = new Object();
            System.out.println("构造:" + object);
            System.out.println("依赖注入:" + object);//此时我们认为依赖注入的扩展性可能会很大
            for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                beanPostProcessor.inject(object);
            }
            System.out.println("初始化:" + object);
            return object;
        }

        private List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
            beanPostProcessors.add(beanPostProcessor);
        }
    }

    static interface BeanPostProcessor {
        public Object inject(Object bean);
    }
}

这个是比较简单的模版方法,希望初学者能好好体会模版方法的使用

常见的后处理器

AutowiredAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor

我们在之前文章中提到过,

public class BeanPostProcessor {
    public static void main(String[] args) {

        //准备一个比较干净的容器
        GenericApplicationContext ctx = new GenericApplicationContext();
        ctx.registerBean("bean1", Bean1.class);
        ctx.registerBean("bean2", Bean2.class);
        ctx.registerBean("bean3", Bean3.class);

        //换一个自动装配候选者解析器,这个后面会详细学习,默认的解析器解析不了String类型
        ctx.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        ctx.registerBean(AutowiredAnnotationBeanPostProcessor.class);//@Autowired、@Value 注解的处理器
        ctx.registerBean(CommonAnnotationBeanPostProcessor.class);//@Resource @PostConstruct @PreDestroy
        //现在运行之后会发现@Autowired、@Value都找到了


        ctx.refresh();
        ctx.close();
    }
}

public class Bean1 {
    private static final Logger log = LoggerFactory.getLogger(Bean1.class);
    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.debug("@Autowired 生效: {}}", bean2);
        this.bean2 = bean2;
    }

    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.debug("@Resource 生效: {}}", bean3);
        this.bean3 = bean3;
    }

    private String port;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}")String port) {
        log.debug("@Value 生效: {}", port);
        this.port = port;
    }

    @PostConstruct
    public void init() {
        log.debug("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy() {
        log.debug("@PreDestroy 生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", port='" + port + '\'' +
                '}';
    }
}
public class Bean2 {
}
public class Bean3 {
}

执行之后会发现这两个处理器的功能和作用,我们这里使用到的容器是GenericApplicationContext,相比于之前的DefaultListableBeanFactory使用更加方便

再来说一个SpringBoot中的一个后处理器,我们常常会用到@ConfigurationProperties注解

//准备一个比较干净的容器
        GenericApplicationContext ctx = new GenericApplicationContext();
        ctx.registerBean("bean1", Bean1.class);
        ctx.registerBean("bean2", Bean2.class);
        ctx.registerBean("bean3", Bean3.class);
        ctx.registerBean("bean4", Bean4.class);
        //换一个自动装配候选者解析器,这个后面会详细学习,默认的解析器解析不了String类型
        ConfigurationPropertiesBindingPostProcessor.register(ctx.getDefaultListableBeanFactory());
        ctx.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        ctx.registerBean(AutowiredAnnotationBeanPostProcessor.class);//@Autowired、@Value 注解的处理器
        ctx.registerBean(CommonAnnotationBeanPostProcessor.class);//@Resource @PostConstruct @PreDestroy
        //现在运行之后会发现@Autowired、@Value都找到了
        
        ctx.refresh();
        System.out.println(ctx.getBean(Bean4.class));
        ctx.close();
ConfigurationPropertiesBindingPostProcessor.register(ctx.getDefaultListableBeanFactory());
        ctx.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

对于@ConfigurationProperties注解的后处理器,可以帮我们解析@ConfigurationProperties注解,那么在这里展示的Bean后处理器我们之后会逐一学习

AutowiredAnnotationBeanPostProcessor

我们在上文其实看到了AutowiredAnnotationBeanPostProcessor是来帮我们解析@Autowired、@Value 注解的Bean后处理器

我们现在来细索运行过程:

public class AutowiredBeanPostProcessor {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //我们之前使用的DefaultListableBeanFactory想要加入Bean需要做一个描述类,相比大家还记得第一讲的AbstractBeanDefinition
        //要先搞一个描述,然后把描述注册到工厂,beanFactory.registerBeanDefinition();
        //我们这里用一个简单的定义方式,这种定义方式会认为你的Bean已经初始化好了
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.registerSingleton("bean3",new Bean3());
        //再来加上一个帮我们解析@Value的自动装配解析器,目前我们知道他可以帮我们解析@Value,其实功能非常强大
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());


        //把AutowiredAnnotationBeanPostProcessor单拿出来,让他去作用于Bean1,如果需要找Bean2和Bean3,去beanFactory里面
        AutowiredAnnotationBeanPostProcessor BeanPostProcessor =
                new AutowiredAnnotationBeanPostProcessor();
        BeanPostProcessor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        //这个Bean后处理器的方法,我们之前是不是学到过呢?在bean的生命周期的依赖注入阶段,我们使用到了的,
        // 第一个参数是我们注入值,第二个是我们处理的Bean,第三个是我们Bean的名称
        BeanPostProcessor.postProcessProperties(null,bean1,"bean1");
        System.out.println(bean1);
        //我们看到第一次打印的时候Bean1什么都没有,而第二次打印则自动注入了进去

    }
}

我们再来看看他的在依赖注入的时候干了什么事:

先找到所有有@autowired注解的方法,或者属性,交给InjectionMetadata封装起来,然后反射调用进行赋值操作

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //我们之前使用的DefaultListableBeanFactory想要加入Bean需要做一个描述类,相比大家还记得第一讲的AbstractBeanDefinition
        //要先搞一个描述,然后把描述注册到工厂,beanFactory.registerBeanDefinition();
        //我们这里用一个简单的定义方式,这种定义方式会认为你的Bean已经初始化好了
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.registerSingleton("bean3",new Bean3());
        //再来加上一个帮我们解析@Value的自动装配解析器,目前我们知道他可以帮我们解析@Value,其实功能非常强大
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //再加一个解析${}的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);


        //把AutowiredAnnotationBeanPostProcessor单拿出来,让他去作用于Bean1,如果需要找Bean2和Bean3,去beanFactory里面
        AutowiredAnnotationBeanPostProcessor BeanPostProcessor =
                new AutowiredAnnotationBeanPostProcessor();
        BeanPostProcessor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
//        System.out.println(bean1);
//        //这个Bean后处理器的方法,我们之前是不是学到过呢?在bean的生命周期的依赖注入阶段,我们使用到了的,
//        // 第一个参数是我们注入值,第二个是我们处理的Bean,第三个是我们Bean的名称
//        BeanPostProcessor.postProcessProperties(null,bean1,"bean1");
//        System.out.println(bean1);
        //我们看到第一次打印的时候Bean1什么都没有,而第二次打印则自动注入了进去


        //那么AutowiredAnnotationBeanPostProcessor到底怎么玩的呢?

        //我们先将上面的代码注释,观察底层代码
        Method method = AutowiredAnnotationBeanPostProcessor.class
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        method.setAccessible(true);
        InjectionMetadata injectionMetadata =
                (InjectionMetadata) method.invoke(BeanPostProcessor, "bean1", Bean1.class, null);//获取加了@Autowired、@Value的成员变量和方法参数
        System.out.println(injectionMetadata);//断点调试我们看到已经解析了@Autowired、@Value的成员变量和方法参数
        injectionMetadata.inject(bean1,"bean1",null);
        System.out.println(bean1);
        //已经生效

那么InjectionMetadata调用inject的时候干了什么呢?

//1.按类型注入成员变脸时:
        //如何按照类型注入呢?
        Field field = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd = new DependencyDescriptor(field,false);//Spring底层会将field封成DependencyDescriptor依赖描述
        Object o = beanFactory.doResolveDependency(dd, null, null, null);
        System.out.println(o);
        //查看打印结果,我们发现已经找到了Bean3并创建
        //2.注入方法变量时:
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 =
                new DependencyDescriptor(new MethodParameter(setBean2,0),false);
        Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o2);
        //3.值注入的时候,相比已经形成了套路
        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor dd3 =
                new DependencyDescriptor(new MethodParameter(setHome,0),false);
        Object o3 = beanFactory.doResolveDependency(dd3, null, null, null);
        System.out.println(o3);
posted @ 2023-12-07 22:56  VayneBeSelf  阅读(56)  评论(0)    收藏  举报