means that in all fields of beans dependencies will be automatic...">

Can @Autowired and default-autowire coexist?

<beans default-autowire="byType /> 

means that in all fields of beans dependencies will be automatically entered, if not more than 1 bean with the desired type.

The question is how it works when using annotations and whether it works at all.

My test showed that even if I use

 @Resource(name="someConcreteFoo") private Foo foo; 

The context tries to autowire the field by type and fails if there are multiple Foo implementations. So, for what I see, default-autowire does not mix with annotations. I could not find anything specific in the documentation.

To expand the question - how does spring work with default autoload when only xml is used. That is, if you have a <property> . Does property embedding include the default value (it should be).

I can do more tests, but I would prefer that the behavior is confirmed by some quotes. Any ideas?

+6
java spring
source share
3 answers

I had a quick hit on debugging this problem, and I think this might be a bug in spring. In my opinion, the problem is related to the following code in AbstractAutowireCapableBeanFactory

 /** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */ protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); } 

Personally, I believe that the order of using the auto-device and InstantiationAwareBeanPostProcessor is incorrect, since the @Resource annotation will be applied only in postProcessPropertyValues, so after auto-installation (by then auto-installation did not work).

Now I don’t know whether there will be an effect on the change in the order of invocations, so that @Resource annotations will be resolved before auto-installation, but this may be something that needs to be raised as an error / fix (I used the following method to load the context of the test application to eliminate this Problems):

  ApplicationContext ctx = new ClassPathXmlApplicationContext("test/appctx.xml") { protected org.springframework.beans.factory.support.DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()) { protected void populateBean(String beanName, org.springframework.beans.factory.support.AbstractBeanDefinition mbd, org.springframework.beans.BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } applyPropertyValues(beanName, mbd, bw, pvs); } }; } }; 

Hope that helps

+3
source share

Edit:

Whether the property attachment sets the default value (it should be).

You're right. If you don't want Spring to add a dependency to a specific bean field, then the @Qualifier annotation can be used to enter the desired dependency. I'm still trying to find documentation that would confirm it - the closest I could find a message on the Spring forum is to override the default-autowire setting with annotation?

Edit: Here is another @ Resource post , considered only after default-autowire = "byName" , which describes the use of the new InstantiationAwareBeanPostProcessor to change the posting order so that @Resource on setter takes precedence over default startup.

+1
source share

As far as I know, the default-autowire attribute defines the default "autowire" mode for those beans connected only to your XML configuration! Then auto-installation based on annotation does not depend on this. @Autowired always by type, @Resource always by name!
See Feedback in Spring 3.9.3 Help:
"If you intend to express an annotation-based injection by name, don’t use @Autowired basically, even if you can technically refer to the bean name via @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific the target component by its unique name, and the declared type is not relevant to the matching process. "

0
source share

All Articles