Spring自动装配匹配类名问题

1.重构的时候遇到Spring按Type装载匹配的Bean的异常,当有两个具象类且是父子关系时(如下图, 父类SPParser4ItemAOImpl和子类SPParser4BrandAOImpl), 通过Spring容器ApplicationContext.getBean按type装载匹配父类时,会匹配到两个实例(自己SPParser4ItemAOImpl和子类SPParser4BrandAOImpl), 装载子类时,只会找到子类实例本身(SPParser4BrandAOImpl). 有兴趣可看下DefaultListableBeanFactory.doGetBeanNamesForType方法, 用了xxx.class.isInstance(beanInstance)去判断.
[img]http://dl2.iteye.com/upload/attachment/0120/3627/dfef030d-f34b-3f30-b61b-4a800f20ca25.png[/img]


@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方法.
[img]http://dl2.iteye.com/upload/attachment/0120/3631/8ad6170b-fb61-3b50-a438-edb738711b61.png[/img]


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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值