1.重构的时候遇到Spring按Type装载匹配的Bean的异常,当有两个具象类且是父子关系时(如下图, 父类SPParser4ItemAOImpl和子类SPParser4BrandAOImpl), 通过Spring容器ApplicationContext.getBean按type装载匹配父类时,会匹配到两个实例(自己SPParser4ItemAOImpl和子类SPParser4BrandAOImpl), 装载子类时,只会找到子类实例本身(SPParser4BrandAOImpl). 有兴趣可看下DefaultListableBeanFactory.doGetBeanNamesForType方法, 用了xxx.class.isInstance(beanInstance)去判断.
@Component
public class SPParser4BrandAOImpl extends SPParser4ItemAOImpl {
@Override
public void parseDataList() {
System.out.println("This is in SPParser4BrandAOImpl");
}
}
@Component
public class SPParser4ItemAOImpl extends SuperSPPageFloorParseAO {
@Override
public void parseDataList() {
System.out.println("This is in SPParser4ItemAOImpl");
}
}
public abstract class SuperSPPageFloorParseAO implements SPPageFloorParserAO {
@Override
public Map<String, String> parseAttrMap() {
return new HashMap<>();
}
}
public interface SPPageFloorParserAO {
void parseDataList();
/**
* 获取 SPPageFloorVO attrMap数据
* @return
*/
Map<String, String> parseAttrMap();
}
@Component
public class SPParser4BannerAOImpl extends SuperSPPageFloorParseAO {
public void parseDataList() {
//是banner的话就进行url组装
System.out.println("This is in SPParser4BannerAOImpl");
}
}
[b][color=darkred]注意,调用的地方是找各自具象类[/color][/b]
SPParser4ItemAOImpl sPParser4ItemAOImpl = (SPParser4ItemAOImpl) context.getBean(SPParser4ItemAOImpl.class);
SPParser4BrandAOImpl sPParser4BrandAOImpl = (SPParser4BrandAOImpl) context.getBean(SPParser4BrandAOImpl.class);
2.Spring自动装配匹配类跟使用的地方是有关联的,如果使用的地方按接口类型或父类去查找, 会匹配到所有实现了接口类型和父类的具象类(SPParser4BannerAOImpl,SPParser4BrandAOImpl,SPParser4ItemAOImpl),程序会报错.
@Component
public class TestApp {
@Autowired
private SPPageFloorParserAO sPPageFloorParserAO;
public void test(){
sPPageFloorParserAO.parseDataList();
}
}
@Autowired
private SuperSPPageFloorParseAO superSPPageFloorParseAO;
public void testSuperClass(){
superSPPageFloorParseAO.parseDataList();
}
解决TestApp的依赖注入时,还是用xxx.class.isInstance(beanInstance)去判断.
3. 在使用Spring注解如 @Component 注册为组件时,如果没有指定名字 @Component("指定的名字"), 而是默认的话,如果class名称为 ABxxx 时会直接返回,而不会将 A 转为小写,因为Spring的判断是:如果第二位是大写,则直接返回.有兴趣可看类AnnotationBeanNameGenerator的generateBeanName和buildDefaultBeanName方法.
4. Qualifier如果在父子具象类中使用,如果Qualifier仅标在父具象类中,通过@Autowired和@Qualifier找父类也会找到两个,还需要把@Qualifier标注在子类上,这样Autowired父类只会找到一个.
@Component
//@Primary
@Qualifier("cold")
public class SPParser4ItemAOImpl extends SuperSPPageFloorParseAO {
@Override
public void parseDataList() {
System.out.println("This is in SPParser4ItemAOImpl");
}
}
@Component
//@Qualifier("需要增加一个新标识跟父类标识区分")
public class SPParser4BrandAOImpl extends SPParser4ItemAOImpl {
@Override
public void parseDataList() {
System.out.println("This is in SPParser4BrandAOImpl");
}
}
@Component
public class TestApp {
@Autowired
//@Qualifier("SPParser4ItemAOImpl")
@Qualifier("cold")
private SPPageFloorParserAO sPPageFloorParserAO;
public void test(){
sPPageFloorParserAO.parseDataList();
}
}
@Test
public void testGetBeanByClazz() {
TestApp testApp = context.getBean(TestApp.class);
testApp.test();
}