spring工厂的自动注入

一、仅一个实现类

这种情况最简单,只需要直接使用@Autowired按类型注入,安全快捷,当然你也可以用@Resource @Qualifier注入,也可以final修饰,写构造方法注入。如:

@RequiredArgsConstructor
public class TestMain {
    private final InterfaceThree three;
}
二、当前接口有多个实现类

如果一个接口有多个实现类,那么你再使用上面的方法就不行了,会报注入异常,但是有时候你就是会有多个实现类 ,那该怎么办呢?

2.1 List方式注入

如果你在写适配器时,你是并不知道未来实现你接口的时候,别人是怎么定义他们的类名的。这个时候,另外一种注入方式就出来了:

/**
 * 你暴露的接口
 */
public interface InterfaceOne {
    String one();
}
/**
 * 实现类1
 */
@Component
public class OneImpl implements InterfaceOne{
    @Override
    public String one() {
        return "one";
    }
}
/**
 * 实现类2
 */
@Component
public class One2Impl implements InterfaceOne{
    @Override
    public String one() {
        return "two";
    }
}

这个时候,你不知道他们的类名,你不能使用名字注入,这个时候,你可以这样:

首先对接口进行一些改造-增加一个校验方法:

/**
 * 你暴露的接口
 */
public interface InterfaceOne {
    String one();
    boolean check(int code);
}

这样子你的实现类都需要实现这个方法,我们可以对这个校验进行一个规则限制:

/**
 * 实现类1
 */
@Component
public class OneImpl implements InterfaceOne{
    @Override
    public String one() {
        return "one";
    }

    @Override
    public boolean check(int code) {
        return code==1;
    }
}
/**
 * 实现类2
 */
@Component
public class One2Impl implements InterfaceOne{
    @Override
    public String one() {
        return "two";
    }

    @Override
    public boolean check(int code) {
        return code==2;
    }
}

这个code我们可以放数据库,可以写enum,这个就很灵活了。

我们在使用时,就可以这样:

@RequiredArgsConstructor
public class TestMain {
    private final List<InterfaceOne> ones;

    public void Test(){
        int code = 1;
        String result = ones.stream()
            	.filter(one->one.check(code))
                .map(one-> one.one())
                .collect(Collectors.toList()).get(0);
        System.out.println(result);
    }
}
2.2 Map方式注入

当然不是只有这种情况,也许还有这么一个场景:一个业务有两种处理方式,根据传来的标识进行选择哪种处理方式。就好像我们在登录的时候,我们可以选择账号密码登录,也可以选择手机号加验证码登录,这时候,我们是知道两种方式的name的。这样子我们可以选择另一种注入方式-map

初始的接口与2.1类似,就不累赘了,直接上改造后的:

@Component("two")
public class TwoImpl implements InterfaceTwo {
    @Override
    public String two() {
        return "two";
    }
}
@Component("two2")
public class Two2Impl implements InterfaceTwo {
    @Override
    public String two() {
        return "two2";
    }
}

可以看到,我们只是改了@Component的value值而已,也就是改了类在spring工厂中的名字,接下来就是使用了:

@RequiredArgsConstructor
public class TestMain {
    private final Map<String, InterfaceTwo> twos;

    public void Test(){
        String result2 = twos.get("two").two();
        System.out.println(result2);
    }
}

ok,是不是很简单。