最近在做項目的時候,發現程序運行的時候有一個nullpointer exception,一臉懵逼因為感覺程序沒什么邏輯。后來發現是因為new出來的component不會自動注入它的元素。
現象:@Component修飾的自定義普通類中@Autowired屬性為null
原因:如果是通過new實例化的對象,脫離了Spring的管理,所以獲取不到Spring注解的屬性值。
在新線程中也會存在注解獲取不到Spring管理的Bean,也是因為new出來的線程,脫離了Spring容器
我在實際開發中遇到有一段公共的代碼,幾個方法都需要掉,但如果單獨拉出來寫一個方法的話,入參又不同,所以想到了用泛型。
比如這是一段公共代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//保存訂單信息,需要多個方法調用
OrderFilterRequest orderFilterRequest =
new
OrderFilterRequest();
btOrderFilterRequest.setUserId(
"1"
);
btOrderFilterRequest.setStatus(
"0"
);
List<Order> orderResultList = orderService.findOrders(orderFilterRequest);
Order result =
null
;
if
(CollectionUtils.isEmpty(orderResultList )){
Order order = CopierUtils.convert(request, Order.
class
);
order.setRealName(customer.getRealName());
order.setIdcardNo(customer.getIdcardNo());
order.setOrderNo(
"order"
+ DateUtil.getYMDHMS());
order.setStatus(
"0"
);
order.setCreateTime(
new
Date());
order.setUpdateTime(
new
Date());
order.setUserId(
"1"
);
result = orderService.createOrder(Order);
}
else
{
Order orderResult = orderResultList.get(
0
);
CopierUtils.copy(request, orderResult);
orderResult.setUpdateTime(
new
Date());
result = orderService.updateOrder(btOrderResult);
}
|
將這段代碼提煉成泛型類:
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
|
@Transactional
(readOnly =
true
)
@Component
public
class
OrderRequest<T>{
@Autowired
private
OrderService orderService;
@Transactional
public
Order orderInfoSave(T request) {
OrderFilterRequest orderFilterRequest =
new
OrderFilterRequest();
btOrderFilterRequest.setUserId(
"1"
);
btOrderFilterRequest.setStatus(
"0"
);
List<Order> orderResultList = orderService.findOrders(orderFilterRequest);
Order result =
null
;
if
(CollectionUtils.isEmpty(orderResultList )){
Order order = CopierUtils.convert(request, Order.
class
);
order.setRealName(customer.getRealName());
order.setIdcardNo(customer.getIdcardNo());
order.setOrderNo(
"order"
+ DateUtil.getYMDHMS());
order.setStatus(
"0"
);
order.setCreateTime(
new
Date());
order.setUpdateTime(
new
Date());
order.setUserId(
"1"
);
result = orderService.createOrder(Order);
}
else
{
Order orderResult = orderResultList.get(
0
);
CopierUtils.copy(request, orderResult);
orderResult.setUpdateTime(
new
Date());
result = orderService.updateOrder(btOrderResult);
}
return
result;
}
}
|
最開始我是這么調用的:
1
2
3
4
5
6
7
8
9
|
public
void
method1(Request1 request ) {
OrderRequest<Request1>
orderCreateRequest =
new
OrderRequest
<Request1>();
Order result = OrderCreateRequest.orderInfoSave(request);
}
public
void
method2(Request2 request ) {
OrderRequest<Request2>
orderCreateRequest =
new
OrderRequest
<Request2>();
Order result = OrderCreateRequest.orderInfoSave(request);
}
|
但是OrderRequest中orderService為null。(在controller層中注入service接口,在service層中注入orderService是有值的),嘗試可很多解決辦法,最后發現,原來spring自定義的類實例化時也需要用注入的方式,不能用new,否則脫離了spring的管理。改成如下方式就可以了:
1
2
3
4
5
6
7
8
9
10
11
12
|
@Autowired
private
OrderRequest<Request1> request1;
@Autowired
private
OrderRequest<Request2> request2;
public
void
method1(Request1 request ) {
Order result = request1.orderInfoSave(request);
}
public
void
method2(Request2 request ) {
Order result = request2.orderInfoSave(request);
}
|
總結:
如果在A類中的屬性b有@Autowired這樣的注解,則類A的實例化不能用new 操作,必須要用注入的方式,否則脫離了spring的管理;
解決方法:
調用ApplicationContextUtil.getApplicationContext().getBean("XXX", XXX.class);方法獲取component