protected @Autowired method can be overridden with non-annotated method to suppress injection; private @Autowired methods with same signature will be called individually across a hierarchy (SPR-6112)

This commit is contained in:
Juergen Hoeller 2009-09-15 15:52:13 +00:00
parent fa2bb722f0
commit fd81aa205d
3 changed files with 65 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@ -83,7 +83,7 @@ public class InjectionMetadata {
doRegisterConfigMembers(beanDefinition, this.injectedMethods); doRegisterConfigMembers(beanDefinition, this.injectedMethods);
} }
private void doRegisterConfigMembers(RootBeanDefinition beanDefinition, Set<InjectedElement> members) { private void doRegisterConfigMembers(RootBeanDefinition beanDefinition, Collection<InjectedElement> members) {
for (Iterator<InjectedElement> it = members.iterator(); it.hasNext();) { for (Iterator<InjectedElement> it = members.iterator(); it.hasNext();) {
Member member = it.next().getMember(); Member member = it.next().getMember();
if (!beanDefinition.isExternallyManagedConfigMember(member)) { if (!beanDefinition.isExternallyManagedConfigMember(member)) {
@ -231,16 +231,8 @@ public class InjectionMetadata {
return false; return false;
} }
InjectedElement otherElement = (InjectedElement) other; InjectedElement otherElement = (InjectedElement) other;
if (this.isField) {
return this.member.equals(otherElement.member); return this.member.equals(otherElement.member);
} }
else {
return (otherElement.member instanceof Method &&
this.member.getName().equals(otherElement.member.getName()) &&
Arrays.equals(((Method) this.member).getParameterTypes(),
((Method) otherElement.member).getParameterTypes()));
}
}
@Override @Override
public int hashCode() { public int hashCode() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -146,6 +146,32 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
bf.destroySingletons(); bf.destroySingletons();
} }
@Test
public void testExtendedResourceInjectionWithSkippedOverriddenMethods() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerResolvableDependency(BeanFactory.class, bf);
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
RootBeanDefinition annotatedBd = new RootBeanDefinition(OverriddenExtendedResourceInjectionBean.class);
bf.registerBeanDefinition("annotatedBean", annotatedBd);
TestBean tb = new TestBean();
bf.registerSingleton("testBean", tb);
NestedTestBean ntb = new NestedTestBean();
bf.registerSingleton("nestedTestBean", ntb);
OverriddenExtendedResourceInjectionBean bean = (OverriddenExtendedResourceInjectionBean) bf.getBean("annotatedBean");
assertSame(tb, bean.getTestBean());
assertNull(bean.getTestBean2());
assertSame(tb, bean.getTestBean3());
assertSame(tb, bean.getTestBean4());
assertSame(ntb, bean.getNestedTestBean());
assertNull(bean.getBeanFactory());
assertTrue(bean.baseInjected);
assertTrue(bean.subInjected);
bf.destroySingletons();
}
@Test @Test
public void testExtendedResourceInjectionWithAtRequired() { public void testExtendedResourceInjectionWithAtRequired() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -934,7 +960,9 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
private ITestBean testBean4; private ITestBean testBean4;
private BeanFactory beanFactory; protected BeanFactory beanFactory;
public boolean baseInjected = false;
public ExtendedResourceInjectionBean() { public ExtendedResourceInjectionBean() {
} }
@ -950,6 +978,11 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
this.nestedTestBean = nestedTestBean; this.nestedTestBean = nestedTestBean;
} }
@Autowired
private void inject(ITestBean testBean4) {
this.baseInjected = true;
}
@Autowired @Autowired
protected void initBeanFactory(BeanFactory beanFactory) { protected void initBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
@ -978,6 +1011,27 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
} }
public static class OverriddenExtendedResourceInjectionBean extends ExtendedResourceInjectionBean<NestedTestBean> {
public boolean subInjected = false;
@Override
public void setTestBean2(TestBean testBean2) {
super.setTestBean2(testBean2);
}
@Override
protected void initBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Autowired
private void inject(ITestBean testBean4) {
this.subInjected = true;
}
}
public static class OptionalResourceInjectionBean extends ResourceInjectionBean { public static class OptionalResourceInjectionBean extends ResourceInjectionBean {
@Autowired(required = false) @Autowired(required = false)

View File

@ -689,16 +689,18 @@ public abstract class ClassUtils {
* <code>targetClass</code> doesn't implement it or is <code>null</code> * <code>targetClass</code> doesn't implement it or is <code>null</code>
*/ */
public static Method getMostSpecificMethod(Method method, Class targetClass) { public static Method getMostSpecificMethod(Method method, Class targetClass) {
if (method != null && targetClass != null && !targetClass.equals(method.getDeclaringClass())) { Method result = method;
if (method != null && !Modifier.isPrivate(method.getModifiers()) &&
targetClass != null && !targetClass.equals(method.getDeclaringClass())) {
try { try {
method = targetClass.getMethod(method.getName(), method.getParameterTypes()); result = targetClass.getDeclaredMethod(method.getName(), method.getParameterTypes());
} }
catch (NoSuchMethodException ex) { catch (NoSuchMethodException ex) {
// Perhaps the target class doesn't implement this method: // Perhaps the target class doesn't implement this method:
// that's fine, just use the original method. // that's fine, just use the original method.
} }
} }
return method; return result;
} }
/** /**