A brief introduction to.@Resource annotations

The @Resource annotation annotation attributes are injected by default as ByName, provided by J2EE

If we wanted to inject by ByType, the code would look like this:

Public class LaController {// Inject @resource (type=LaService. Class) private LaService LaService; }Copy the code

If the LaService interface has two implementation classes, and both implementation classes are detected by Spring, an error will be reported during injection: nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.netty.use.nettyuse.service.LaService’ available: expected single matching bean but found 2: la2ServiceImpl,laServiceImpl

Type can also be an implementation class, for example:

Public class LaController {// Inject @resource (type= la2ServicePl.class) private LaService LaService; }Copy the code

This will inject the La2ServiceImpl instance and the above error will not occur.

Two. Injection source code details

Code to AbstractAutowireCapableBeanFactory populateBean method of a class

/ / whether there is instantiated related BeanPostProcessor Boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors (); boolean needsDepCheck = (mbd.getDependencyCheck() ! = RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; / / call processing methods of attribute value PVS = ibp. PostProcessPropertyValues (PVS, filteredPds, bw. GetWrappedInstance (), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }}Copy the code

InstantiationAwareBeanPostProcessor has an implementation class called CommonAnnotationBeanPostProcessor, this class will be @ the attribute of the Resource annotation for assignment.

1. Find all attributes of the @Resource annotation

Using Java reflection, find all the Fields in the class and determine if the @Resource annotation is marked on the property

if(field.isAnnotationPresent(Resource.class))
Copy the code

If the condition is true, a ResourceElement is built. Let’s look at the ResourceElement class

private class ResourceElement extends LookupElement { private final boolean lazyLookup; Constructor public ResourceElement(Member Member, AnnotatedElement ae, @nullable PropertyDescriptor pd) {super(Member, pd); Resource resource = ae.getAnnotation(Resource.class); // Attribute name String resourceName = resource-.name (); // Attribute type Class<? > resourceType = resource.type(); this.isDefaultName = ! StringUtils.hasLength(resourceName); if (this.isDefaultName) { resourceName = this.member.getName(); if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) { resourceName = Introspector.decapitalize(resourceName.substring(3)); } } else if (embeddedValueResolver ! = null) { resourceName = embeddedValueResolver.resolveStringValue(resourceName); } if (Object.class ! = resourceType) { checkResourceType(resourceType); } else { // No resource type specified... check field/method. resourceType = getResourceType(); } this.name = (resourceName ! = null ? resourceName : ""); this.lookupType = resourceType; String lookupValue = resource.lookup(); this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName()); Lazy lazy = ae.getAnnotation(Lazy.class); this.lazyLookup = (lazy ! = null && lazy.value()); } @Override protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) { return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName)); }}Copy the code

Finally, all of the ResourceElements from the class marked with the @Resource attribute are added to the LinkedList. Finally, an InjectionMetadata object is wrapped.

2.@Resource Property value injection

Now that we have all the @Resource attributes, we can loop through the injection of those attributes.

Property injection core principle = reflection +getBean method.

The getBean method gets the Bean object and then assigns the property by calling the set method of Field. Let’s take a look at the code snippet:

if (this.isField) {
   Field field = (Field) this.member;
   ReflectionUtils.makeAccessible(field);
   field.set(target, getResourceToInject(target, requestingBeanName));
}
Copy the code