Sping高级(源码)--- 1.4Bean后处理器

1.4Bean后处理器

1.4.1Bean后处理器的作用:为Bean生命周期各个阶段提供扩展

例子:后置处理器解析各个注解

  • 新建类Bean2、Bean3
public class Bean2 {
}

public class Bean3 {
}
  • Bean1
/**
 * @author 我见青山多妩媚
 * @date Create on 2022/9/30 17:17
 */
@Slf4j
public class Bean1 {
    private Bean2 bean2;

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

    private Bean3 bean3;

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

    private String home;

    @Autowired
    private void setHome(@Value("${JAVA_HOME}") String home){
        log.info("@Value生效:{}",home);
    }

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

    @PreDestroy
    public void destroy(){
        log.info("@PreDestroy生效");
    }
}
  • A04Application类
public class A04Application {
    public static void main(String[] args) {
        //是一个【干净】的容器,因为里面没有添加后处理器
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean(Bean1.class);
        context.registerBean(Bean2.class);
        context.registerBean(Bean3.class);
        
        //初始化容器,执行bean后处理器,添加beanFactory后处理器,初始化所有单例
        context.refresh();

        context.close();

    }
}

我们先启动一次,看看里面都加载了什么

Sping高级(源码)--- 1.4Bean后处理器_第1张图片


里面就创建了三个bean对象

我们依次添加后处理器,查看后面解析的内容

  • 添加@Autowired解析,在创建bean3后添加
 		//添加后置处理器解析,不加的话只有上面的注册bean,实际上bean1内的注解都没解析出来
        //1.解析@Autowired 和 @Value,如果使用默认的AutowireCandidateResolver,@Value的值注入无法被解析,会报错,所以这里重新设置他的解析
		//依赖注入阶段解析
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new 		ContextAnnotationAutowireCandidateResolver());
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);

运行结果:

image-20221003105451971

此时解析的内容挺多的,两个注解都解析了,但是还有一个部分没有解析,我们接着往上添加

  • 添加@Resource的解析
		//2.解析@Resource(依赖注入解析) 和 @PostConstruct(初始化前解析) @PreDestroy(销毁前)
        context.registerBean(CommonAnnotationBeanPostProcessor.class);

运行结果:

Sping高级(源码)--- 1.4Bean后处理器_第2张图片


注解全部解析,至于为什么@Resource@Autowired先解析,上面已经提到过,不再赘述

1.4.2常见的后处理器

@ConfigurationProperties解析

  • Bean4
package com.spring.demo.demo04;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author 我见青山多妩媚
 * @date Create on 2022/10/3 11:22
 */

//匹配配置文件中的键值信息,以java开头
@ConfigurationProperties(prefix = "java")
public class Bean4 {
    private String home;

    private String version;

    public String getHome() {
        return home;
    }

    public void setHome(String home) {
        this.home = home;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return "Bean4{" +
                "home='" + home + '\'' +
                ", version='" + version + '\'' +
                '}';
    }
}
  • 解析
	//3.解析@ConfigurationProperties,初始化前解析
	ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
	System.out.println(context.getBean(Bean4.class));

运行结果:

Bean4{home='E:\enviornment\java\IntelliJ IDEA 2020.1.2\jbr', version='11.0.7'}

1.4.3@AutowiredAnnotationBeanPostProcessor后处理器执行分析

处理解析

对Bean1添加toString()方法,添加测试类

//AutowiredAnnotationBeanPostProcessor 运行分析
public class DigInAutowired {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        //创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean2",new Bean2());
        beanFactory.registerSingleton("bean3",new Bean3());
        //加上@Value,以便获取值
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        //1.查找哪些属性、方法加了@Autowired 称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        //执行依赖注入,解析@Autowired
        processor.postProcessProperties(null,bean1,"bean1");

        System.out.println(bean1);
        //2.调用InjectionMetadata 进行依赖注入,注入时按类型查找值
    }
}

运行结果:

Bean1{bean2=null, bean3=null, home='null'}
20:26:55.398 [main] INFO com.spring.demo.demo04.Bean1 - @Value生效:${JAVA_HOME}
20:26:55.406 [main] INFO com.spring.demo.demo04.Bean1 - @Autowired生效:com.spring.demo.demo04.Bean2@5cdd8682
Bean1{bean2=com.spring.demo.demo04.Bean2@5cdd8682, bean3=null, home='null'}

可以看到,我们的结果是没问题的,解析了@Autowired的注解

另外,我们也可以得到哪些方法和参数上加了对应的注解

  • DigInAutowired类追加
 //2.调用InjectionMetadata 进行依赖注入,注入时按类型查找值
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        
        //获取bean1上加了@Vaule和@Autowired的成员变量和方法参数
        InjectionMetadata metadata =(InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(metadata);

使用debug运行,运行结果:

Sping高级(源码)--- 1.4Bean后处理器_第3张图片


找到方法或参数上的注解

		//3.如何按类型查找值
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        //封装,false-->如果bean3没有依赖注入,返回的是null,如果设为true,那么将抛异常
        DependencyDescriptor d1 = new DependencyDescriptor(bean3, false);
        Object o = beanFactory.doResolveDependency(d1, null, null, null);
        System.out.println(o);

        //加了注解的方法怎么找到
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor d2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
        Object o1 = beanFactory.doResolveDependency(d2, null, null, null);
        System.out.println(o1);

		//值注入
        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        //sethome 方法的第0个参数
        DependencyDescriptor d3 = new DependencyDescriptor(new MethodParameter(setHome, 0), false);
        Object o2 = beanFactory.doResolveDependency(d3, null, null, null);
        System.out.println(o2);

运行结果:

com.spring.demo.demo04.Bean3@43d7741f
com.spring.demo.demo04.Bean2@69379752
${JAVA_HOME}

你可能感兴趣的:(技术,java,前端,安全)