在之前的文章里Field injection is not recommended介绍了为什么要尽量避免Field injection, 这篇文章主要介绍如何解决该问题.
使用Field injection的代码像下面
class controller{
@Auowired
private A a;
...
}
Java8 之前, 推荐使用的是constructor injection, 我们的处理变为
class controller{
private A a;
@Auowired
public controller(A a){
this.a=a;
}}
改成上方式的话, new controller的时候, 就必须使用参数. 这对于使用IDE的程序员来说, 可以很好的避免了bug(空指针). 然而, 自由性被限制, 当我们不确定某些属性是否一定要实现时, construct method 要写若干个, 代码量也增加了.
class controller{
private A a;
...
@Auowired
public controller(A a){
this.a=a;
}
public controller(A a,B b){
...
}
public controller(A a,B b,C c){
...
}}
上述代码, 如果映射到编程思想, 也就是COC(convention over configuration), 我们希望要修改的地方得到修改即可.
综上 Java 8 之前的field injection 和 constructor injection的优点, 我们可以使用optional类.
实现代码如下:
class controller{
@Autowired
private Optional<A> a;
}
这里有两个问题, 1.原代码中使用到A类的如何改? 2.Optional会自动匹配到A接口的实现类吗?
1)原代码中使用到A类的如何改?
原来的代码
methodA(){
if(a!=null) dosomething;
}
methodB(){
if(a!=null) return something;
}
对应则是
methodA(){
if(a.isPresent()) dosomething;
}
methodB(){
if(a.isPresent()) return something;
}
methodB(){
a.get();
}
当然, 也可以如下
methodA(){
a.map(a->dosomething);
}
methodB(){
a.ifPresent(a->dosomething);
}
方法若干… 函数式的方法, 基本都对应一个场景, 需要多看Javadoc
2)Optional会自动匹配到A接口的实现类吗?
答: 会
摘自IBM
使用 @Autowired 注解进行装配,只能是根据类型进行匹配。@Autowired 注解可以用于 Setter 方法、构造函数、字段,甚至普通方法,前提是方法必须有至少一个参数。@Autowired 可以用于数组和使用泛型的集合类型。然后 Spring 会将容器中所有类型符合的 Bean 注入进来。@Autowired 标注作用于 Map 类型时,如果 Map 的 key 为 String 类型,则 Spring 会将容器中所有类型符合 Map 的 value 对应的类型的 Bean 增加进来,用 Bean 的 id 或 name 作为 Map 的 key。
上述文章说道, map是可以匹配得到的, 所以这种机制同样适用于optional.
测试代码如下:
@Autowired
Map<String, Object> a;
@RequestMapping(value = "/iaaa")
public void a()
System.out.println(a.size());
}