javascript
Spring_01_IoC初级总结
1.IoC簡介 (轉載)
(原文:http://jinnianshilongnian.iteye.com/blog/1413846) ?via:@jinnianshilongnian
1.1、IoC是什么
Ioc—Inversion of Control,即“控制反轉”,不是什么技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什么,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
●誰控制誰,控制什么:傳統Java SE程序設計,我們直接在對象內部通過new進行創建對象,是程序主動去創建依賴對象;而IoC是有專門一個容器來創建這些對象,即由Ioc容器來控制對 象的創建;誰控制誰?當然是IoC 容器控制了對象;控制什么?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙創建及注入依賴對象;為何是反轉?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。
1.2、IoC能做什么
IoC 不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導我們如何設計出松耦合、更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,難于測試;有了IoC容器后,把創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是 松散耦合,這樣也方便測試,利于功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC容器來創建并注入它所需要的資源了。
IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫對象找相應的依賴對象并注入,而不是由對象主動去找。
1.3、IoC和DI
DI—Dependency Injection,即“依賴注入”:組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態的將某個依賴關系注入到組件之中。依賴注入的目的并非為軟件系統帶來更多功能,而是為了提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,那我們來深入分析一下:
●誰依賴于誰:當然是應用程序依賴于IoC容器;
●為什么需要依賴:應用程序需要IoC容器來提供對象需要的外部資源;
●誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象;
●注入了什么:就是注入某個對象所需要的外部資源(包括對象、資源、常量數據)。
IoC和DI由什么關系呢?其實它們是同一個概念的不同角度描述,由于控制反轉概念比較含糊(可能只是理解為容器控制對象這一個層面,很難讓人想到誰來維護對象關系),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,“依賴注入”明確描述了“被注入對象依賴IoC容器配置依賴對象”。
2、代碼實現(原創)
2.1準備工作
2.1.1jar包與項目目錄結構
spring原項目下
spring\ 1.aopalliance-1.0.jar 2.aopalliance-alpha1.jar 3.aspectjrt.jar?aspectjweaver.jar 4.commons-logging.jar
Spring\spring-framework-3.0.0.RELEASE\dist里的所有jar
2.1.2vo包,dao包,service包代碼
public calss student{//voprivate String name;private Integer age;/** getter and setter */ } public interface IStudentDao {//daopublic void add(Student student); } public interface IStudentDaoByMybatis {public void add(Student student); } public class StudentDaoImpl implements IStudentDao{//dao.impl@Overridepublic void add(Student student) {System.out.println(student.getName()+"成功通過JDBC添加");} } public class StudentDaoByMybatisImpl implements IStudentDaoByMybatis{//dao.impl@Overridepublic void add(Student student) {System.out.println(student.getName()+"成功通過Mybatis添加");} } public interface IStudentService {//service包public void add(Student student); }2.1.3 spring.xml
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- xmlns:aop="http://www.springframework.org/schema/aop" 聲明要用aop的標簽xsi:schemaLocation= aop的標簽地址"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" --> </beans>2.2注入IoC(通過spring.xml)
? 2.2.1重點標簽與屬性解釋
?(一)bean的生命周期,兩個常用屬性:lazy-init和scope
? 1.懶加載屬性lazy-init,每次啟動IoC時,通常需要啟動的大的數據庫啟動很耗時(比如數據庫連接池),用再加載,通過這種方式提高速度,true是開啟,false是關閉,default是默認,beans的全局沒有設置時default默認是false關閉?
? 2.scope,設置模式,singleton是單例,prototype是多例,每次用到IoC容器里的bean時,單例用的是一個,多例可用多個,singleton是單例的,整個項目共用一個對象,應用很多(錘子);prototype是多例的,項目會用多個對象,多用于Controller注入(釘子)
? 3.init-method,bean初始化時調用的方法,參數里寫bean對應的類里的方法名,多用于初始化字典值
4.destroy-method,bean銷毀時用的方法 ,參數里寫bean對應的類里的方法名,多用于數據庫連接的關流(現在開始可以自動關了).注意:這個bean的scope用prototype的時候(也就是多例時),不調用該bean的destroy-method
(二)依賴注入, autowire自動裝載可省略以下<property>,通過反射的方式,獲取這個bean對應的類里的各種信息
1.byName通過set方法的名稱注入(裝載)(原理是反射),根據ServiceImpl里得到的set方法的名稱
2.byType通過實現的接口類型注入(裝載), 比如上面這個org.jsoft.dao.IStudentDao
3.no是不自動注入(裝載)
2.2.2 java代碼
StudentServiceImpl里的代碼
public class StudentServiceImpl implements IStudentService{private IStudentDao studentDao;private IStudentDaoByMybatis studentDaoByMybatis;// public IStudentDao getStudentDaoByMybatis() {//對比ByName用法時用 // return studentDao; // } // public void setStudentDaoByMybatis(IStudentDao studentDaoByMybatis) { // this.studentDao = studentDaoByMybatis; // }//需要寫getset方法public IStudentDaoByMybatis getStudentDaoByMybatis() {return studentDaoByMybatis;}public void setStudentDaoByMybatis(IStudentDaoByMybatis studentDaoByMybatis) {this.studentDaoByMybatis = studentDaoByMybatis;}public IStudentDao getStudentDao() {return studentDao;}public void setStudentDao(IStudentDao studentDao) {this.studentDao = studentDao;}// @Override // public void add(Student student) { // studentDao.add(student); // //System.out.println(student.getName()); // // }@Overridepublic void add(Student student) {studentDaoByMybatis.add(student);//System.out.println(student.getName());} // @Override // public void add(Student student) { // studentDaoByMybatis.add(student); // //System.out.println(student.getName()); // // }public void a(){//bean初始化時調用System.out.println("StudentServiceImpl.a(),初始化");}public void b(){//bean銷毀時調用System.out.println("StudentServiceImpl.b(),銷毀");} } //測試用的Main方法 //ApplicationContext 是接口,下面的ClassPathXmlApplicationContext也可以用,后者可以用.close()方法 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/spring.xml"}); Student s = new Student(); s.setName("Joy"); IStudentService studentService = context.getBean("studentService",IStudentService.class); IStudentService studentService2 = context.getBean("studentService",IStudentService.class);//scope的屬性 //singleton是單例,只用一個,studentService和studentService2被賦予的是一個bean對象,內存地址一樣,所以會返回true; //而prototype是多例,會給studentService賦予來自一個bean的不同的對象 System.out.println(studentService == studentService2);//對比對象在內存里的地址,一樣就返回true,studentService.add(s); context.close();2.3注入IoC(通過注解)
2.3.1spring.xml的配置
注意:
1.beans的xmlns:context="http://www.springframework.org/schema/context"這句話一定要有,聲明要用注解
2.beans的xsi:schemaLocation屬性里一定要有"http://www.springframework.org/schema/context
? ? ? ? ? ?http://www.springframework.org/schema/context/spring-context-3.0.xsd "注解的地址
3.下面的context標簽,寫上,注解才會生效
<?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/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- --><context:annotation-config/><!-- 掃描組件 --><context:component-scan base-package="org.jsoft"/></beans>2.3.2注解
1@Component("這個bean的id")都可以用,寫在聲明類名的上邊
2.@Service("這個bean的id")用在serviceimpl里聲明類名的上邊
3@Repository("這個bean的id")dao持久層里聲明類名的上邊
4.@Autowired 寫在serviceImpl里的聲明過的dao的set方法上? ?@Qualifier("用到的dao層的bean的id")寫在這個方法聲明參量的括號里參量類型的前邊? ? ? ? ? ?*不常用*
5.@Controller 用在C層里
6.@Resource("用到的bean的id"),聲明的Service或者Dao上面,里面寫對應的bean的id
2.3.3Demo(沒有@Controller)
1.dao層,只需要寫在實現類里,
@Repository("studentDaoImpl")//注入bean public class StudentDaoImpl implements IStudentDao{//實現了IStudentDao@Overridepublic void add(Student student) {System.out.println(student.getName()+"成功通過JDBC添加");} } @Repository("studentDaoByHibernateImpl") public class StudentDaoByHibernateImpl implements IStudentDao{//也實現了IStudentDao@Overridepublic void add(Student student) {System.out.println(student.getName()+"成功通過Hibernate添加");} } @Repository("studentDaoByMybatisImpl") public class StudentDaoByMybatisImpl implements IStudentDaoByMybatis{//實現了另外一個@Overridepublic void addByMybatis(Student student) {System.out.println(student.getName()+"成功通過Mybatis添加");} }2.service層,同樣地只需要寫在實現類里
@Service(value="studentService") public class StudentServiceImpl implements IStudentService{//@Resource(name="studentDaoImpl")private IStudentDao studentDao;private IStudentDao studentDaoByHibernate;@Resource(name="studentDaoByMybatisImpl")private IStudentDaoByMybatis studentDaoMyBatis;//@Resource會通過暴力反射找到的bean名字,沒有用getset方法 // public IStudentDao getStudentDao() { // return studentDao; // } // public void setStudentDao(IStudentDao studentDao) { // this.studentDao = studentDao; // }// @Override // public void add(Student student) { // studentDao.add(student); // // }@Overridepublic void add(Student student) {studentDaoByHibernate.add(student);}@Overridepublic void addByMybatis(Student student) {studentDaoMyBatis.addByMybatis(student);}public IStudentDao getStudentDao() {return studentDao;}//也可以自動裝載,無需寫@Resourcepublic void setStudentDao(IStudentDao studentDao) {this.studentDao = studentDao;}public IStudentDao getStudentDaoByHibernate() {return studentDaoByHibernate;}@Autowiredpublic void setStudentDaoByHibernate(@Qualifier("studentDaoByHibernateImpl")IStudentDao studentDaoByHibernate) {this.studentDaoByHibernate = studentDaoByHibernate;}public IStudentDaoByMybatis getStudentDaoMyBatis() {return studentDaoMyBatis;}public void setStudentDaoMyBatis(IStudentDaoByMybatis studentDaoMyBatis) {this.studentDaoMyBatis = studentDaoMyBatis;}3.main方法的測試與結果
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/spring.xml"}); Student s = new Student(); s.setName("Joy"); IStudentService studentService = context.getBean("studentService",IStudentService.class); studentService.add(s); context.close();總結
以上是生活随笔為你收集整理的Spring_01_IoC初级总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu下apt-get方式Git的
- 下一篇: Spring_02_AOP初级总结