在前兩篇文章中,我們講了java web環境搭建 和 java web項目搭建,現在看下spring ioc在java中的運用,開發工具為Intellij Idea。
1.簡介IoC(Inversion of Control
)通常稱為控制反轉,是Spring框架的核心。即通過Spring容器控制對象之間的依賴關系,而不是對象自己通過new的方式去創建依賴的對象,相對于主動去創建對象,這種失去對對象的控制便叫做控制反轉,控制反轉用另一種角度描述或者更好的一種理解方式來講,便是DI(Dependency Injection
)依賴注入,對象只需關注業務邏輯本身即可,而不需關注依賴的對象從哪里來,交給容器注入即可,從而降低程序之間的耦合度。
依賴注入在spring中有兩種配置方式,一是xml配置Bean的方式,二是自動裝配檢測Bean
web-inf/dispatcher-servlet.xml
中注入service層的實現類,加入如下代碼<bean id="demoUserService" class="com.ganji.demo.service.user.DemoUserServiceImpl" />
@Inject
自動搜索xml中的bean配置,注入依賴。// 聲明對象 DemoUserServiceImpl實現DemoUserService接口@Inject private DemoUserService demoUserService;@RequestMapping(value="/index", method = {RequestMethod.GET})public ModelAndView index(){ DemoUserEntity demoUser=demoUserService.GetDemoUser(1); modelAndView.addObject("demoUser", demoUser); modelAndView.setViewName("home"); return modelAndView;}
我們在屬性前加了@Inject
,這里依賴javax.inject.Inject
包 ,在模塊pom里加入如下依賴即可
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> </dependency>
如果我們想在service
層依賴注入調用dao層對象操作數據庫,則跟service層類似,我們在web層的web-inf/dispatcher-servlet.xml
注入dao
層的實現,加入如下代碼
<bean id="demoUserDao" class="com.ganji.demo.dao.gcrm.hibernate.DemoUserDaoHibernate"></bean><bean id="demoUserService" class="com.ganji.demo.service.user.DemoUserServiceImpl" autowire="byType"> <property name="demoUserDao" ref="demoUserDao"></property></bean>
ref
指像bean
的實現類,如果是值類型或String
類型可以用value
指定,設定值即可,如value=5
。在service
層,我們可以在DemoUserServiceImpl
層里聲明demoUserDao
私有屬性,并公開屬性set方法,然后調用
//聲明屬性private DemoUserDao demoUserDao;//通過屬性的set方法,注入對象public void setDemoUserDao(DemoUserDao demoUserDao){ this.demoUserDao=demoUserDao;}public DemoUserEntity GetDemoUser(int id) { return demoUserDao.getDemoUser(id);}
構造器注入類似于屬性注入,在xml中用constructor-arg
來指定,這里我們在web層的web-inf/dispatcher-servlet.xml
配置如下
<bean id="demoUserService" class="com.ganji.demo.service.user.DemoUserServiceImpl" autowire="byType"> <constructor-arg name="demoUserDao" ref="demoUserDao"></constructor-arg> <constructor-arg name="userName" value="張三"></constructor-arg></bean>
在service層,我們創建構造函數
private DemoUserDao demoUserDao;private String userName;public DemoUserServiceImpl(DemoUserDao demoUserDao,String userName){ this.demoUserDao=demoUserDao; this.userName=userName;}//在方法里既可以調用了,如下代碼 public DemoUserEntity GetDemoUser(int id) { System.out.println("execute service getdemouser "+userName); return demoUserDao.getDemoUser(id);}
@Inject
注解,類似2.1.2中demoUserService的實現,這樣Spring框架會自動搜索bean對應的實現類,可以在bean處設置根據名稱或類型,即autowire="byType" or autowire="byName"
,也可以全局設置,即在根目錄beans下面聲明default-autowire="byName"
,具體如下。<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans" default-autowire="byName" >
如果每個實現類都要配置bean元素的話,項目如果很大的情況下,太多的bean,xml文件的bean管理配置就成了一個問題,很慶幸的事,spring提供了自動裝配檢測bean注入依賴的功能。
我們依賴<context:component-scan>
查找使用注解所標注的類,這些注解如下
@Component --通用的構造性注解,標識該類為Spring組件 @Controller --標識將該類定義為Spring MVC Controller 這里我們用在web層 @Service --標識將該類定義為服務,這里我們用在Service層 @Repository --標識將該類定義為數據倉庫,這里我們用在Dao層
具體用法如下圖示例
web層調用@Controllerpublic class HelloWorldController {
service層調用@Servicepublic class DemoUserServiceImpl implements DemoUserService {
dao層調用@Repositorypublic class DemoUserDaoHibernate implements DemoUserDao {
注解后,我們需要在web層的web-inf/dispatcher-servlet.xml
配置組件掃描<context:component-scan>
,分別掃描web、service。dao層,具體如下
<!-- 開啟controller注解支持 --><!-- use-default-filters="false" 只掃描指定的注解 --><context:component-scan base-package="com.ganji.demo.web.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /></context:component-scan><!--服務層自動依賴注入--><context:component-scan base-package="com.ganji.demo.service"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /></context:component-scan><!--Dao層依賴注入--><context:component-scan base-package="com.ganji.demo.dao"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /></context:component-scan>
同時,我們需要在xml命名空間里加入context支持,xmlns:context="http://www.springframework.org/schema/context"
和相應的xsi具體如下
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byName" >
上一步配置好后,我們只需要聲明調用對象的屬性即可,如下web層如下
// 聲明對象 DemoUserServiceImpl實現DemoUserService接口@Inject private DemoUserService demoUserService;@RequestMapping(value="/index", method = {RequestMethod.GET})public ModelAndView index(){ DemoUserEntity demoUser=demoUserService.GetDemoUser(1); modelAndView.addObject("demoUser", demoUser); modelAndView.setViewName("home"); return modelAndView;}
service層如下
@Injectprivate DemoUserDao demoUserDao;public DemoUserEntity GetDemoUser(int id) { return demoUserDao.getDemoUser(id);}
按2.2.1和2.2.2配置操作后,即可實現自動檢查依賴注入bean,不用在xml中配置繁瑣的bean元素,由框架通過反射自動尋找對象實現。
新聞熱點
疑難解答