您现在的位置是:首页 >技术交流 >自定义组件中如何注入Spring底层的组件网站首页技术交流
自定义组件中如何注入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()方法中就是如此