关于为什么要使用@Lookup
的原因,在我之前的博客Spring注解之@Lookup中有写到。
先看一段有问题的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AHandler extends Handler{
public AHandler(Handler next) {
super(next);
}
@Override
public void d0() {
System.out.println("A");
}
}
@Component
public class HandlerFactory {
private Handler handler;
public HandlerFactory() {
this.handler = aHandler();
}
@PostConstruct
protected void init() {
}
@Lookup
private AHandler aHandler() {
return new AHandler(null);
}
}
|
这段代码里有3个问题。3个什么问题,暂且不说,下面先简述一下@Lookup
注解的原理。
以上面的错误代码为例:
- Spring通过Cglib创建HandlerFactory的增强代理子类,然后通过代理类处理
@Lookup
。 LookupOverrideMethodInterceptor
通过BeanFactory的getBean方法获取AHandler实例。
问题在哪呢?
不能再HandlerFactory的构造函数
中调用aHandler()方法。
上面的代码这么调用,相当于没有使用@Lookup
。因为想要@Lookup
生效,必须要先有代理类,而执行构造方法的时候还没有。
不能使用private
修饰aHandler()方法。
Cglib不能代理private
修饰的方法,所以@Lookup
也会失效。
aHandler()方法应该传入需要的参数。
这里,从aHandler()传入一个null和直接使用new AHandler(null)使用区别的。前者使用BeanFactory的getBean(Class requiredType, Object… args),后者使用getBean(Class requiredType)。
详见LookupOverrideMethodInterceptor
的intercept。
所以,可以将错误的代码改成这样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| @Component
public class HandlerFactory {
private Handler handler;
public HandlerFactory() {
}
@PostConstruct
protected void init() {
this.handler = aHandler(null);
}
@Lookup
protected AHandler aHandler(Handler next) {
return new AHandler(next);
}
}
|