spring @Value原理及自定义实现
@Value 原理
@Value通过AutowiredAnnotationBeanPostProcessor完成属性注入
Person
@Data
@Component
public class Person {
@Value("瓜田李下")
private String name;
private Integer age;
}
AutowiredAnnotationBeanPostProcessor实例化调用栈
# AutowiredAnnotationBeanPostProcessor构造函数创建对象
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.(AutowiredAnnotationBeanPostProcessor.java:162)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211)
# SimpleInstantiationStrategy类
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
# AbstractAutowireCapableBeanFactory类
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1326)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$215.1489193907.getObject(Unknown Source:-1)
# DefaultSingletonBeanRegistry类
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- locked <0xf9e> (a java.util.concurrent.ConcurrentHashMap)
# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
# PostProcessorRegistrationDelegate类
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:237)
# AbstractApplicationContext
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:567)
- locked <0xf9f> (a java.lang.Object)
# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:10)
属性注入调用栈
# AutowiredAnnotationBeanPostProcessor.postProcessProperties:执行属性注入
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
# AbstractAutowireCapableBeanFactory类
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$211.1448805967.getObject(Unknown Source:-1)
# DefaultSingletonBeanRegistry类
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- locked <0x1696> (a java.util.concurrent.ConcurrentHashMap)
# AbstractBeanFactory类
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
# DefaultListableBeanFactory类
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)
# AbstractApplicationContext类
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
- locked <0x1697> (a java.lang.Object)
# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:10)
AutowiredAnnotationBeanPostProcessor
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
protected final Log logger = LogFactory.getLog(this.getClass());
private final Set> autowiredAnnotationTypes = new LinkedHashSet(4);
private String requiredParameterName = "required";
private boolean requiredParameterValue = true;
private int order = 2147483645;
@Nullable
private ConfigurableListableBeanFactory beanFactory;
private final Set lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap(256));
private final Map, Constructor>[]> candidateConstructorsCache = new ConcurrentHashMap(256);
private final Map injectionMetadataCache = new ConcurrentHashMap(256);
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class); //处理@Autowired注解
this.autowiredAnnotationTypes.add(Value.class); //处理@Value注解
try {
this.autowiredAnnotationTypes.add(ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
this.logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
} catch (ClassNotFoundException var2) {
}
}
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//属性注入
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs); //属性注入
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
********
内部类:AutowiredMethodElement处理方法注入
private class AutowiredMethodElement extends InjectedElement {
private final boolean required;
private volatile boolean cached;
@Nullable
private volatile Object[] cachedMethodArguments;
public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {
super(method, pd);
this.required = required;
}
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (!this.checkPropertySkipping(pvs)) {
Method method = (Method)this.member;
Object[] arguments;
if (this.cached) {
try {
arguments = this.resolveCachedArguments(beanName);
} catch (NoSuchBeanDefinitionException var8) {
arguments = this.resolveMethodArguments(method, bean, beanName);
}
} else {
arguments = this.resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) { //如果方法参数不为null,设置属性值
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
} catch (InvocationTargetException var7) {
throw var7.getTargetException();
}
}
}
}
private Object[] resolveCachedArguments(@Nullable String beanName) {
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
********
内部类:AutowiredFieldElement处理字段注入
private class AutowiredFieldElement extends InjectedElement {
private final boolean required;
private volatile boolean cached;
@Nullable
private volatile Object cachedFieldValue;
public AutowiredFieldElement(Field field, boolean required) {
super(field, (PropertyDescriptor)null);
this.required = required;
}
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field)this.member;
Object value;
if (this.cached) {
try {
value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
} catch (NoSuchBeanDefinitionException var7) {
value = this.resolveFieldValue(field, bean, beanName);
}
} else {
value = this.resolveFieldValue(field, bean, beanName);
}
if (value != null) { //如果value不为null,设置字段属性
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
InjectionMetadata
public class InjectionMetadata {
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//属性注入
Collection checkedElements = this.checkedElements;
Collection elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
if (!((Collection)elementsToIterate).isEmpty()) {
Iterator var6 = ((Collection)elementsToIterate).iterator();
while(var6.hasNext()) {
InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
element.inject(target, beanName, pvs);
} //属性注入
}
}
********
内部类:InjectedElement
public abstract static class InjectedElement {
protected final Member member;
protected final boolean isField;
@Nullable
protected final PropertyDescriptor pd;
@Nullable
protected volatile Boolean skip;
protected InjectedElement(Member member, @Nullable PropertyDescriptor pd) {
this.member = member;
this.isField = member instanceof Field;
this.pd = pd;
}
public final Member getMember() {
return this.member;
}
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
//属性注入,该方法在子类中进行了重写
if (this.isField) {
Field field = (Field)this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, this.getResourceToInject(target, requestingBeanName));
} else {
if (this.checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method)this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, this.getResourceToInject(target, requestingBeanName));
} catch (InvocationTargetException var5) {
throw var5.getTargetException();
}
}
}
protected final Class> getResourceType() {
protected final void checkResourceType(Class> resourceType) {
protected void clearPropertySkipping(@Nullable PropertyValues pvs) {
protected boolean checkPropertySkipping(@Nullable PropertyValues pvs) {
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return null;
}
public boolean equals(@Nullable Object other) {
public int hashCode() {
public String toString() {
自定义注解
application.properties
person.age=20
Person
@Data
@Component
public class Person {
@CustomValue("瓜田李下")
private String name;
@CustomValue("${person.age}")
private Integer age;
}
CustomBeanFactoryPostProcessor
@Configuration
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
beanFactory = configurableListableBeanFactory;
}
@Bean
public AutowiredAnnotationBeanPostProcessor initAutowiredAnnotationBeanPostProcessor(){
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(){
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
ReflectionUtils.doWithLocalFields(bean.getClass(), field -> {
CustomValue customValue = field.getAnnotation(CustomValue.class);
if (customValue != null){
ReflectionUtils.makeAccessible(field);
String value = customValue.value();
if (value != null && !"".equals(value)){
if (!value.startsWith("$")){
field.set(bean,value);
}else {
TypeConverter typeConverter = new SimpleTypeConverter();
field.set(bean,typeConverter.convertIfNecessary(beanFactory.resolveEmbeddedValue(value),field.getType()));
}
}
}
});
return pvs;
}
};
autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(CustomValue.class);
return autowiredAnnotationBeanPostProcessor;
}
}
HelloController
@RestController
public class HelloController {
@Resource
private Person person;
@RequestMapping("/hello")
public String hello(){
System.out.println(person);
return person.toString();
}
}
localhost:8080/hello:点击运行,控制台输出
2022-04-26 18:13:47.454 INFO 4224 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 774 ms
2022-04-26 18:13:47.725 INFO 4224 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-26 18:13:47.734 INFO 4224 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.414 seconds (JVM running for 1.865)
2022-04-26 18:13:53.480 INFO 4224 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-26 18:13:53.480 INFO 4224 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-04-26 18:13:53.481 INFO 4224 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Person(name=瓜田李下, age=20)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)