当前位置:网站首页>@Autowired注解的原理
@Autowired注解的原理
2022-07-25 08:18:00 【Hypnos924】
@Autowired注解的原理
直入主题,首先我们来解释@Autowired注解的用处,即自动满足bean之间的依赖注入
@Autowired注解的用法
含义:向属性注入javaBean,按照类型通过set方法进行自动装配
替换:
位置:修饰成员变量
注意:
[email protected]默认按照类型装配
2.如果spring容器中没有可以与之匹配的类,则会报异常
NoSuchBeanDefinitionException
3.如果spring容器中有多个类型可以与之匹配,@Autowire注解会自动切换为按照名称装配,如 果还没有则会报错
NoUniqueBeanDefinitionException
@Autowired注解原理
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
} else {
List<InjectedElement> elements = new ArrayList();
// 需要处理的目标类
Class targetClass = clazz;
do {
List<InjectedElement> currElements = new ArrayList();
// 通过反射获取该类所有的字段,并遍历每一个字段,并通过方法findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回auotowired相关属性
ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
MergedAnnotation<?> ann = this.findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = this.determineRequiredStatus(ann);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
MergedAnnotation<?> ann = this.findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);
}
boolean required = this.determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
}
}
});
//有多个@Autowired修饰的注解,都加在currElements这个容器里面,一起处理
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
} while(targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
}
返回包含所有带有autowire注解修饰的一个InjectionMetadata集合
public InjectionMetadata(Class<?> targetClass, Collection<InjectionMetadata.InjectedElement> elements) {
this.targetClass = targetClass;
this.injectedElements = elements;
}
拿到目标类,就可以实现依赖注入了
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
if (!this.validatedBeanNames.contains(beanName)) {
if (!this.shouldSkip(this.beanFactory, beanName)) {
List<String> invalidProperties = new ArrayList();
PropertyDescriptor[] var6 = pds;
int var7 = pds.length;
for(int var8 = 0; var8 < var7; ++var8) {
PropertyDescriptor pd = var6[var8];
if (this.isRequiredProperty(pd) && !pvs.contains(pd.getName())) {
invalidProperties.add(pd.getName());
}
}
if (!invalidProperties.isEmpty()) {
throw new BeanInitializationException(this.buildExceptionMessage(invalidProperties, beanName));
}
}
this.validatedBeanNames.add(beanName);
}
return pvs;
}
调用InjectionMetadata中的inject方法
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
Collection<InjectionMetadata.InjectedElement> 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);
}
}
}
遍历之后再调用inject方法
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();
}
}
}
总的来说其核心还是反射,通过反射获取目标类所有的Field和Method信息,然后判是否被@Autowired注解,如果有那么就自动装配,并将需要自动装配的元素,封装成AutowiredFieldElement(针对字段)或AutowiredMethodElement(针对方法)对象;
调用AutowiredFieldElement或AutowiredMethodElement的inject方法,通过反射,调用容器的getBean()方法找到需要注入的Bean对象,然后注入到目标Bean中;
边栏推荐
- Idea reads configuration files such as validationmessages.properties Chinese garbled
- Raspberrypico serial communication
- Raspberry pie 4B ffmpeg RTMP streaming
- 475-82(230、43、78、79、213、198、1143)
- Dijkstra sequence (summer vacation daily question 5)
- 一次简单的SQL注入靶场练习
- 第3章业务功能开发(查询线索)
- Sun Tzu's art of war
- Raspberry pie 4B parsing PWM
- 一款强大的端口扫描工具(nmap)
猜你喜欢

Advanced C language (XII) - dynamic memory management
Mysql-5.7 installation

Summary of SQL skills in data warehouse development

MVC mode three-tier architecture

DIY can decorate the mall system, you can also have!

node+js搭建时间服务器

Science: listening to music can really relieve pain. Chinese scientists reveal the neural mechanism behind it

Pricing is arbitrary, products are difficult to distinguish between true and false, and platforms are running away. Will the Tibetan market continue to be popular?

Idea failed to start the project yamlexception Chinese file encoding format

华为设备远程登录(Telnet、SSH)配置
随机推荐
Dirty data and memory leakage of ThreadLocal
Efcore's solution of multi tenant zero script, table and database read-write separation under SaaS system
Machine learning theory and case analysis (Part2) -- Regression
Teach you to understand the computer optometry sheet
Database query optimization
Chapter 3 business function development (modifying clues, data echo and modifying data)
刷题《剑指Offer》day01
R language error
RK3399开发板I2C4挂载EEPROM实例
A simple hotel background management system based on jsp+servlet+mysql
Numpy learning
IP command usage details
Niuke dynamic planning training
Blue and white porcelain used by Charles
机器学习理论及案例分析(part2)--回归
【黑马程序员】Redis学习笔记005:企业级解决方案
【FFmpeg】mp4转yuv
文献学习(part101)--CONVEX BICLUSTERING
[5g NR] UE registration rejection reason
MVC mode three-tier architecture