Talking more about AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor object is used to dynamically place objects that depend on the dependent object. Perhaps some of you are wondering how this object can do that, right? Me too, and that’s why I’ve been through the code of the AutowiredAnnotationBeanPostProcessor class to see what this object actually did.

OK, first I read its constructor, the content is as follows:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

/**

* Create a new AutowiredAnnotationBeanPostProcessor

* for Spring's standard {@link Autowired} annotation.

* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.

*/

@SuppressWarnings("unchecked")

public AutowiredAnnotationBeanPostProcessor() {

this.autowiredAnnotationTypes.add(Autowired.class);

this.autowiredAnnotationTypes.add(Value.class);

try {

this.autowiredAnnotationTypes.add((Class<? extends Annotation>)

ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));

logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");

} catch (ClassNotFoundException ex) {

// JSR-330 API not available - simply skip.

}

}

Here, you see, this class has a variable called autowiredAnnotationTypes that contains information about three classes, Autowired.class, Value.class, and Inject.class. It is a variable type Set:


1

private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();


This variable is used in 3 different ways to handle 3 annotations: @Autowired, @Value and @Inject.Take a look at these three methods:


1

2

3

4

5

6

7

@Override

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {

if (beanType != null) {

InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);

metadata.checkConfigMembers(beanDefinition);

}

}

This method is for @Autowired annotation.



1

2

3

4

5

6

7

8

9

10

11

12

13

@Override

public PropertyValues postProcessPropertyValues(

PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

?

InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

try {

metadata.inject(bean, beanName, pvs);

}

catch (Throwable ex) {

throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);

}

return pvs;

}

This method is for @Value annotation. The use of this annotation, I will say in another tutorial.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

* 'Native' processing method for direct calls with an arbitrary target instance,

* resolving all of its fields and methods which are annotated with {@code @Autowired}.

* @param bean the target instance to process

* @throws BeansException if autowiring failed

*/

public void processInjection(Object bean) throws BeansException {

Class<?> clazz = bean.getClass();

InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);

try {

metadata.inject(bean, null, null);

}

catch (Throwable ex) {

throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);

}

}

This method is for @Inject annotation. The use of this annotation, I will also be covered in another tutorial.

The common point of these three methods is that it calls to another method called findAutowiringMetadata(). And in this method, there is the buildAutowiringMetadata() method, reading the buildAutowiringMetadata() method, you will visualize what the AutowiredAnnotationBeanPostProcessor object does to handle the cases in which you declare @Autowired annotation in the variable, in the method, and in the constructor. Same for @Value annotation and @Inject annotation.

Look at the two methods, I just said.



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {

// Fall back to class name as cache key, for backwards compatibility with custom callers.

String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());

// Quick check on the concurrent map first, with minimal locking.

InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);

if (InjectionMetadata.needsRefresh(metadata, clazz)) {

synchronized (this.injectionMetadataCache) {

metadata = this.injectionMetadataCache.get(cacheKey);

if (InjectionMetadata.needsRefresh(metadata, clazz)) {

if (metadata != null) {

metadata.clear(pvs);

}

try {

metadata = buildAutowiringMetadata(clazz);

this.injectionMetadataCache.put(cacheKey, metadata);

}

catch (NoClassDefFoundError err) {

throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +

"] for autowiring metadata: could not find class that it depends on", err);

}

}

}

}

return metadata;

}

And


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {

LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();

Class<?> targetClass = clazz;

?

do {

final LinkedList<InjectionMetadata.InjectedElement> currElements =

new LinkedList<InjectionMetadata.InjectedElement>();

?

ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {

@Override

public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {

AnnotationAttributes ann = findAutowiredAnnotation(field);

if (ann != null) {

if (Modifier.isStatic(field.getModifiers())) {

if (logger.isWarnEnabled()) {

logger.warn("Autowired annotation is not supported on static fields: " + field);

}

return;

}

boolean required = determineRequiredStatus(ann);

currElements.add(new AutowiredFieldElement(field, required));

}

}

});

?

ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {

@Override

public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {

Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);

if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {

return;

}

AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);

if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {

if (Modifier.isStatic(method.getModifiers())) {

if (logger.isWarnEnabled()) {

logger.warn("Autowired annotation is not supported on static methods: " + method);

}

return;

}

if (method.getParameterTypes().length == 0) {

if (logger.isWarnEnabled()) {

logger.warn("Autowired annotation should be used on methods with parameters: " + method);

}

}

boolean required = determineRequiredStatus(ann);

PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);

currElements.add(new AutowiredMethodElement(method, required, pd));

}

}

});

?

elements.addAll(0, currElements);

targetClass = targetClass.getSuperclass();

}

while (targetClass != null && targetClass != Object.class);

?

return new InjectionMetadata(clazz, elements);

}

I think you can read this code, right?

要查看或添加评论,请登录

Kevin zhou的更多文章

  • Spring – BeanFactory

    Spring – BeanFactory

    The first foremost thing when we talk about spring is dependency injection which is possible because spring is actually…

  • Difference Between BeanFactory and ApplicationContext

    Difference Between BeanFactory and ApplicationContext

    1. Overview The Spring Framework comes with two IOC containers – BeanFactory and ApplicationContext.

  • SOLVING THE N+1 PROBLEM IN ORMS

    SOLVING THE N+1 PROBLEM IN ORMS

    SOLVING THE N+1 PROBLEM IN ORMS THE N+1 PROBLEM ORMs are tools that write SQL requests for you. Because you use a nice…

  • How I Accidentally Built an API Business

    How I Accidentally Built an API Business

    In this article, I’ll share my journey of building an API business, the technology behind it, and how to build your own…

  • How I Learned to Code and Built a Real Software Product in 6 Months

    How I Learned to Code and Built a Real Software Product in 6 Months

    On May 21st, 2020 I wrote my first-ever line of code as part of Harvard’s CS50 online course. I was a 30 year old with…

    1 条评论
  • How to Convert PDF to Images with Imagemagick

    How to Convert PDF to Images with Imagemagick

    How to Convert PDF to Images with Imagemagick In this post, I want to share how to accomplish this task with…

    1 条评论
  • Design Patterns - Facade Pattern

    Design Patterns - Facade Pattern

    Facade Design Pattern | Introduction Facade is a part of Gang of Four design pattern and it is categorized under…

  • Advantages of ERP

    Advantages of ERP

    Advantages of ERP Now that we’ve cleared up some misconceptions, it’s time to move onto why companies all around the…

  • Configure postfix as relay for macOS Sierra

    Configure postfix as relay for macOS Sierra

    Configure postfix as relay for macOS Sierra Source: https://www.developerfiles.

  • How to Register & Use Laravel Service Providers

    How to Register & Use Laravel Service Providers

    If you've ever come across the Laravel framework, it's highly unlikely that you haven't heard of service containers and…

社区洞察

其他会员也浏览了