Spring通過父類注入公用屬性的技巧
XML配置方式提取父類
在使用Spring + Hibernate框架,或者SSH2等框架的時候,在開發中只有一個基本的DAO是現在的非常流行的做法。然後,在看過多份這種程式碼以後,都是在每個業務類中宣告瞭一個DAO屬性,並且在Bean配置中,對每個業務類分別注入DAO。具體情形示例如下:
BaseDAO程式碼:
public class BaseDAO {
public String service() {
return "Success!";
}
}
Services程式碼:
//第一個業務類
public class ServiceA {
public String service() {
return baseDAO.service();
}
protected BaseDAO baseDAO;
public void setBaseDAO(BaseDAO baseDAO) {
this.baseDAO = baseDAO;
}
}
//第二個業務類
public class ServiceB {
public String service() {
return baseDAO.service();
}
protected BaseDAO baseDAO;
public void setBaseDAO(BaseDAO baseDAO) {
this.baseDAO = baseDAO;
}
}
Spring的Bean配置如下:
<bean id="baseDAO" class="com.watson.BaseDAO" /> <bean id="serviceA" class="com.watson.ServiceA"> <property name="baseDAO" ref="baseDAO" /> </bean> <bean id="serviceB" class="com.watson.ServiceB"> <property name="baseDAO" ref="baseDAO" /> </bean>
這樣的做法是現在的主流。這樣做不是說那裡錯了,還是那句老話:這樣做肯定不優美,誰讓人有時候是一根筋呢?
能夠想到的辦法是用一個父類來包含一些業務層公用的業務邏輯和屬性。所以可以將上面的程式碼和配置。
Services程式碼改寫如下:
//所有業務類的父類
public class BaseService {
protected BaseDAO baseDAO;
public void setBaseDAO(BaseDAO baseDAO) {
this.baseDAO = baseDAO;
}
}
//第一個業務類
public class ServiceA extends BaseService {
public String service() {
return baseDAO.service();
}
}
//第二個業務類
public class ServiceB extends BaseService {
public String service() {
return baseDAO.service();
}
}
Spring的Bean配置改寫如下:
<bean id="baseDAO" class="com.watson.BaseDAO" /> <bean id="BaseService" class="com.watson.BaseService" /> <property name="baseDAO" ref="baseDAO" /> </bean> <bean id="serviceA" class="com.watson.ServiceA" /> <bean id="serviceB" class="com.watson.ServiceB" />
這樣一來是不簡潔了很多?尤其在實際專案有太多Bean的時候。然後,這裡不會達到我們預想的結果,因為這裡會出現如下的錯誤:
exception: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException ...... root cause: java.lang.NullPointerException:......
而出錯程式碼就是每個業務中呼叫baseDAO的那行程式碼。這說明注入失敗了。翻閱Spring的Bean注入詳解之後,很快就可以找應該設定子類Bean配置的parent屬性。所以這裡可以修改設定。
Spring的Bean配置改寫如下:
<bean id="baseDAO" class="com.watson.BaseDAO" /> <bean id="BaseService" class="com.watson.BaseService" /> <property name="baseDAO" ref="baseDAO" /> </bean> <bean id="serviceA" class="com.watson.ServiceA" parent="baseService" /> <bean id="serviceB" class="com.watson.ServiceB" parent="baseService" />
這個時候再執行,就不會報錯了。原理是:在Spring的子類Bean配置中,其parent屬性作用是指定其父類,並繼承父類的注入屬性。不僅如此,子類還可以修改或者覆蓋父類的屬性值。例如上述程式碼中的子類修改父類的baseDAO到屬性:
<bean id="BaseService" class="com.watson.BaseService" /> <property name="baseDAO" ref="baseDAO" /> </bean> <bean id="serviceA" class="com.watson.ServiceA" parent="baseService" /> <property name="baseDAO" ref="baseDAO2" /> </bean>
而對於父類的List等集合屬性,子類可以繼承父類的值,並且在其基礎上進行增加新的值:
<bean id="BaseService" class="com.watson.BaseService" /> <property name="listValue"> <list> <value>listValue1</value> <value>listValue2</value> </list> </property> </bean> <bean id="serviceA" class="com.watson.ServiceA" parent="baseService" /> <property name="listValue"> <list> <value>listValue3</value> <value>listValue4</value> </list> </property> </bean>
Annotation方式提取父類
上面的方法是在XML配置檔案中進行的配置。而對現在Spring3流行的Annotation方式,其實更加的方便,完整示例如下:
BaseDAO程式碼:
@Component
public class BaseDAO {
public String service() {
return "Success!";
}
}
Services程式碼:
//所有業務類的父類
public class BaseService {
@Autowired
protected BaseDAO baseDAO;
}
//第一個業務類
@Component
public class ServiceA extends BaseService {
public String service() {
return baseDAO.service();
}
}
//第二個業務類
@Component
public class ServiceB extends BaseService {
public String service() {
return baseDAO.service();
}
}
Action層程式碼:
@Controller
@RequestMapping(value = "/testaction")
public class TestAction {
@Autowired
private ServiceA service;
@RequestMapping(value = "/")
public @ResponseBody String home(Model model) {
return service.service();
}
}
這裡根本就不需要進行parent屬性子類的配置,可以完美的提取父類,並且可以順利的使用父類的公用屬性。至於原理,沒有去看原始碼的處理方式,估計和上述XML配置是異曲同工的,只是在這裡增加了對父類的檢測。
相關文章
- spring注入配置檔案屬性到java類SpringJava
- 揭秘Java反射:如何輕鬆獲取類的屬性及父類屬性Java反射
- 獲取類屬性值,當前類,父類
- kubectl技巧之通過jsonpath擷取屬性JSON
- kubectl技巧之通過go-template擷取屬性Go
- Spring原始碼系列:依賴注入(三)-屬性注入Spring原始碼依賴注入
- 父類和子類物件的獲取值的方式驗證,透過父類屬性的方式獲取不到值,需要使用get方法物件
- 通過代理的方式讓Spring注入ServletSpringServlet
- Spring 原始碼分析之 bean 依賴注入原理(注入屬性)Spring原始碼Bean依賴注入
- 在url中通過屬性名獲取屬性值
- spring原始碼解析之IOC容器(四)——屬性注入Spring原始碼
- 基於autofac的屬性注入
- jquery通過name屬性匹配元素jQuery
- 通過clss屬性查詢元素
- Spring @Autowired 注入小技巧Spring
- 捉蟲記之dozer對映父類屬性被重寫
- Spring中利用配置檔案和@value注入屬性值Spring
- Spring IOC容器【p名稱空間注入屬性值 】Spring
- Spring review--常用屬性String、int、list、set、Map的注入SpringView
- Rust 通過屬性禁用 lint 警告Rust
- js通過元素的class屬性獲取元素JS
- 2.常見父項屬性
- 子類擁有父類物件所有的屬性和方法,但無法訪問物件
- C#通過反射獲取物件屬性,列印所有欄位屬性的值C#反射物件
- 這篇文章,我們來談一談Spring中的屬性注入Spring
- javascript通過class屬性獲取元素的程式碼JavaScript
- Python 類的屬性與例項屬性Python
- spring中通過constructor來注入引數的四種方式SpringStruct
- 獲得類的屬性
- Spring 原始碼(16)Spring Bean的建立過程(7)屬性填充Spring原始碼Bean
- 淺析如何通過PHP類的反射來實現依賴注入PHP反射依賴注入
- WPF通過附加屬性控制視窗關閉
- .net中通過反射得到所有的私有欄位(包括父類)反射
- Spring的BeanFactoryPostProcessor中屬性SpringBean
- Aop踩坑!記一次模板類呼叫注入屬性為空的問題
- python過載父類的__init__方法Python
- Python 類屬性的理解Python
- Day30--類的屬性