spring IOC/DI思想
傳統使用new 類注入的方式造成程式碼的耦合,例如: StudentAction類,依賴StudentBiz,並呼叫服務層StudentBiz中的getName()方法
public student StudentAction{
StudentBiz studentBiz=new StudentBiz();
public vooid printSTUDENTnAME(){
System.out.println("學生:"+studentBiz.getName())
}
}
服務層StudentBiz又通過new例項化StudnetDao,依賴studnetDao,並呼叫了studnetDao的getName()方法。
這樣類與類之間層層的依賴會造成,當修改一個類時,其相關依賴的類都要重新編譯才能使用,可謂是牽一髮而動全身,付出的代價太大,故spring推出了依賴注入的解決方案。
1.工廠模式:(使用工廠模式建立物件)
public interface IStudentBiz{}
public class StudentBiz implements IStudentBiz{}
public class StudentBizFactory{ public static IStudentBiz getInstance(){return new StudentBiz();}}
public class StudentAction{IStudnetBiz studnetBiz=studnetFactory.getInstance()}
此時,服務類studentBiz發生變化,只需調整studengFactory程式碼,studentAction不用動。
2.spring的控制反轉(ioc)或依賴注入(DI)
spring可以管理很多類(java不就是類與類之間的運作嗎,需要預先宣告bean,即在application.xml中配置bean,類之間的依賴關係,如:A依賴B,則在A類中需要定義對B類賦值的setter方法,這是spring對管理類的唯一的要求。)舉例如下:
public interface IstudentDao{public String getName()}
public class StudnetDao implemtns IstudentDao{@override public String getName(return ''李四"//實際中李四是從資料庫中取出來//studentDao.getName()) }
//業務層
public interface IStudnetBiz {public String getName()}
public class StudnetBiz implemtns IStudentBiz{ IStudentDao studntDao; @Override public String getName(){return studnetDao.getName();}}
//與studnetDao.getName()對應的setter方法是:
public void setStudnetDao(IStudnetDao studentDao){this.studentDao=studentDao}
web層的setter:
public class StudentAction{ IstudentBiz studentBiz; public void setStudnetDao(IStudnetDao studentDao){this.studentDao=studentDao} public void printName(System.out.println(studentBiz.getName())}
spring中的配置:
<bean id="studentDao" class="xxx.xxx.impl.StudentDao"/>
//id是bean的標記
<bean id="studentBiz" class="xxx.xxx.impl.StudentBiz">
//呼叫setStudentDao(),為studentBiz的studentDao屬性賦值
<property name=""studentDao>
<ref bean="studentDao"/>
</property>
//properties是子標記,定義了對應類的setter方法
//ref是子標記,定義了需要傳遞給setter方法的例項物件
main方法測試:
ApplicationContext ctx=new ClassPathXmlApplicationContext(xx/xx/application.xml)
StudentAction studentAction=(StudentAction)ctx.getBean("studentAction");
studentAction.printName();
依賴注入到此結束。
下面是代理模式:
被代理類:student(或客戶,明星比如劉德華)
代理類:studentProxy(律師,代理人,經紀人)
二者必須都要實現同一個介面Istudent
public interface Istudent{ public void writework()}
public class Student implements Istudent{@Override public vioid writehomework(println("我是被代理類,我在寫作業"))}
注意,傳參是傳被代理的介面。
public class StudentProxy implements Istudent{private Istudent student; public StudentProxy(Isudent student){this.student=student} @Override public vioid writehomework{(println("執行前的日誌列印"),student.write.wroteHomwork();,println("執行後的日誌列印")},
測試程式碼:
Istudent studnet=new Studnet();
student.writeHomework();
Istudent studentProxy=new Studnet StudnetProxy(studnet);
studnetProxy.writeHomework();
總結:
最後做事情的是代理類,代理類按照被代理類的意願做了事情,並列印了日誌,它在不修改被代理類的前提下對他加入了日誌功能,而且日誌完全由代理類進行控制,做到了日誌功能和也業務功能的分離,還需增加功能時,按同樣的方式建立代理類即可。