“This is the 10th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
Resource-CommonAnnotationBeanPP
Two optional values for the Resource annotation:
- name = “?”
- type = ? .class
The structure is the same:
-
Find the injection point (@Resource)
- Here, the findResourceMetadata call to buildMetadata returns an error if it resolves to a static field annotated by @Resource, whereas autowired does not.
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<? > beanType, String beanName) { super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }Copy the code
The Element implementation class of metadata is ResourceElement:
public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) { super(member, pd); Resource resource = ae.getAnnotation(Resource.class); // Here is the value of the annotation String resourceName = resource.name(); Class<? > resourceType = resource.type(); This.isdefaultname =! This.isdefaultname =! StringUtils.hasLength(resourceName); if (this.isDefaultName) { resourceName = this.member.getName(); // If the name of the resource has a set, If (this.member instanceof Method && resourcename.startswith ("set") && resourcename.length () > 3) {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); } //Object is the default value of type, which checks to see if it matches 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()); }Copy the code
-
Field property injection
- Inject here is implemented by the parent class
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
// Two auto-injected PPS are similar
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
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, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throwex.getTargetException(); }}}// Implement getResourceToInject in subclasses:
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
// Lazy is used to construct proxy objects, similar to autowired
// Next up is getResource
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
/ / jndi, ejb related
if (StringUtils.hasLength(element.mappedName)) {
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
if (this.alwaysUseJndiLookup) {
return this.jndiFactory.getBean(element.name, element.lookupType);
}
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the 'resourceFactory' property");
}
// Normal is just straight here
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
String name = element.name;
// Default's BF is of this class
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
// The core logic for the @resource lookup bean is here
// isDefaultname is the value of the attribute name
// Check the bean factory to see if there are any beans, and resolve if there are none
Before / / fallbackToDefaultTypeMatch, refers to whether can find the corresponding bean by class type
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && ! factory.containsBean(name)) { autowiredBeanNames =new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object"); }}// If the bean is included, or if the annotation contains the name of the bean, it can be obtained directly from BF
else{ resource = beanFactory.resolveBeanByName(name, descriptor); autowiredBeanNames = Collections.singleton(name); }}else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
for (String autowiredBeanName : autowiredBeanNames) {
if(requestingBeanName ! =null&& beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); }}}return resource;
}
Copy the code
conclusion
Dependency injection IOC selection steps:
@Autowired
private Object resource;
Copy the code
-
First look for beans by type
-
Screening:
-
candidate=true?
-
Is it generic?
-
The Qualifier? (@qualifier can modify beans, if any, and the corresponding @autoWired will preferentially select the bean with the same name specified by this annotation if specified by the same name.)
-
Primary does not exist?
-
Priority from small to big?
-
The name
-
- Autowire and Resource:
- autowired:
- The static variable, autowired, is skipped
- First by type, then by name
- Spring provides
- resource:
- Static variable resource, an error
- First by name, then by type
- Provide the javax.mail
- autowired: