您现在的位置是:首页 >技术交流 >自定义组件中如何注入Spring底层的组件网站首页技术交流

自定义组件中如何注入Spring底层的组件

怀梦 2024-06-14 17:17:40
简介自定义组件中如何注入Spring底层的组件

1.概述

自定义的组件要想使用Spring容器底层的一些组件,比如ApplicationContext(IOC容器)、底层的BeanFactory等等,那么只需要让自定义组件实现XxxAware接口即可。此时,Spring在创建对象的时候,会调用XxxAware接口中定义的方法注入相关的组件

2.XxxAware接口概览

在Spring中,类似于ApplicationContextAware接口的设计有很多,本质上,Spring中形如XxxAware这样的接口都继承了Aware接口,我们来看下Aware接口的源码,如下所示:

package org.springframework.beans.factory;

public interface Aware {

}

Aware接口是Spring 3.1版本中引入的接口,在Aware接口中,并未定义任何方法

3.XxxAware接口案例

3.1.ApplicationContextAware接口

通过ApplicationContextAware接口我们可以获取到IOC容器

创建一个Red类,实现ApplicationContextAware接口,并在实现的setApplicationContext()方法中将ApplicationContext输出,如下所示:

package com.tianxia.springannotation.entity;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 红色类
 * @author liqb
 * @date 2023-04-23 15:43
 **/
@Component
public class Red implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("传入的IOC:" + applicationContext);
        this.applicationContext = applicationContext;
    }
}

3.2.BeanNameAware接口

通过BeanNameAware接口获取到当前bean在Spring容器中的名称,如下所示:

package com.tianxia.springannotation.entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;

/**
 * 红色类
 * @author liqb
 * @date 2023-04-23 15:43
 **/
@Component
public class Red implements ApplicationContextAware, BeanNameAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("传入的IOC:" + applicationContext);
        this.applicationContext = applicationContext;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("当前bean的名字:" + name);
    }
}

3.3.EmbeddedValueResolverAware

通过EmbeddedValueResolverAware接口能够获取到String值解析器,如下所示:

package com.tianxia.springannotation.entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

/**
 * 红色类
 * @author liqb
 * @date 2023-04-23 15:43
 **/
@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("传入的IOC:" + applicationContext);
        this.applicationContext = applicationContext;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("当前bean的名字:" + name);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String resolveStringValue = resolver.resolveStringValue("你好,${os.name},我的年龄是#{20*18}");
        System.out.println("解析的字符串:" + resolveStringValue);
    }
}

StringValueResolver会解析那些String类型的值的,如果这个String类型的值里面有一些占位符,那么也会把这些占位符给解析出来,最后返回一个解析后的值

运行测试方法,输出的结果信息如下所示:

/**
 * 测试方法
 * @author liqb
 * @date 2023-05-08 11:51
 */
@Test
public void test03() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);

    Color color = (Color) applicationContext.getBean("color02");
    System.out.println(color);

    applicationContext.close();
}

在这里插入图片描述

3.XxxAware原理

XxxAware接口的底层原理是由XxxAwareProcessor实现类实现的,也就是说每一个XxxAware接口都有它自己对应的XxxAwareProcessor实现类。 例如,ApplicationContextAware接口的底层原理就是由ApplicationContextAwareProcessor类实现的。从ApplicationContextAwareProcessor类的源码可以看出,其实现了BeanPostProcessor接口,本质上是一个后置处理器。

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;
}

分析ApplicationContextAware接口的原理为例,看看Spring是怎么将ApplicationContext对象注入到Red类中的

在Red类的setApplicationContext()方法上打一个断点,并运行测试方法,如下所示:

在这里插入图片描述

ApplicationContext对象已经注入到Red类的setApplicationContext()方法中了

然后定位到了postProcessBeforeInitialization()方法

在这里插入图片描述

在这里插入图片描述

postProcessBeforeInitialization()方法所在的类就是ApplicationContextAwareProcessor,在postProcessBeforeInitialization()方法中调用的invokeAwareInterfaces()方法,如下所示

在这里插入图片描述

Red类实现了ApplicationContextAware接口后,Spring为啥会将ApplicationContext对象自动注入到setApplicationContext()方法中就是如此

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。