关于 spring 中的 xxaware接口,aware 的意思是
意识到,对。。。有兴趣
也就是说实现了 aware 接口意味着对这些内容有兴趣。
比如ApplicationEventPublisherAware
意味着对ApplicationEventPublisher
有兴趣,BeanNameAware
则表明对BeanName
有兴趣
在 spring 中存在一个标记接口,就叫Aware
spring 中所有的 aware 类的接口都继承了这个接口,而所有的 Aware 接口也如其 doc 所说
The actual method signature is determined by individual subinterfaces but should typically consist of just one void-returning method that accepts a single argument.
提供了一个 setxx 的 void 函数。
也许有些同学还不知道,其实这种方法也属于 DI
的一种,名为接口注入。
我们一般情况下最经常使用的是 spring 提供的 set 注入和构造器注入,但是在有些时候需要访问 spring 的bean 时,使用 Aware 接口也许是一个更好的选择,至于为什么。。。
我认为这种接口形式的注入更能说明其特征,这个类是关心这部分内容的,也就是说它应该依赖了这部分内容,毕竟如非必要勿增实体,但最好是在需要说明特征时才使用这种方式,其他依赖的情况其实用 set 和 构造器更方便,并且耦合更加松散。
在我自己的项目中有时候也会不得已进行到这一步,某些接口都需要一个成员,成员需要在构造实现类时进行注入,就会增加一个接口,专门用于访问这个成员,之前不知道取什么名字好,一般都是 xxd 或者 xxed,后来学习了 spring 的 aware 之后就都取了这个名字xxAware,看起来也顺眼多了。
比如我希望所有 handler 和 executor接口在执行时打印日志都能够打印 name,创建一个如下接口
interface Named{
void setName(String name);
}
而用下面这个接口看起来就更顺眼一些
interface NameAware{
void setName(String name);
}
扩展操作
关于 这个 aware 其实也可以解决下面这个问题
如何在自己 new 出来的对象中访问 spring 管理的 bean
一般脑洞不是特别大的情况下,询问百度同学,会找到一个 BeanGet 的类,其实现了 ApplicationContextAware 接口,并且其set 函数实际上是给一个静态变量赋值。看起来没什么问题,用起来稍微注意一下接口的访问时机就好,但总觉得有点变扭,毕竟成员函数操作类变量。
我之前也是这样子做的,但是后来突然开窍了,可以用下面这种更加自然的方式实现
假设需要手动 new 的类为 A,A需要依赖的bean 的类型为 B,手动new A 类的bean 为 C
-
声明一个需要依赖的 bean类型的 aware 接口也就是BAware
-
在会自行创建实例的 bean 中,也就是 C,注入需要依赖的 bean,也就是 B
-
在实现类中实现 AAware 接口
-
使用 instanceof 访问接口
原始
interface T{
//t 的接口
}
class A implements T{
B b;
//获取 b
b=BeanGet.getBean("b",B.class);
//
}
class C{
void createA(){
new A();
}
}
自然的方式
interface BAware{
void setB(B b);
}
class A implements T,AAware{
B b;
//获取 b
//b=BeanGet.getBean("b",B.class);不用
//
}
class C{
B b;//注入到 C
void createA(){
T t=new A();
if(t instanceof AAware)
t.setB(b)
}
}