Spring中IoC的入门实例.docx
《Spring中IoC的入门实例.docx》由会员分享,可在线阅读,更多相关《Spring中IoC的入门实例.docx(16页珍藏版)》请在冰豆网上搜索。
![Spring中IoC的入门实例.docx](https://file1.bdocx.com/fileroot1/2022-11/27/fe55d414-21e6-4396-9484-ef0a12583ba4/fe55d414-21e6-4396-9484-ef0a12583ba41.gif)
Spring中IoC的入门实例
Spring中IoC的入门实例
Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用。
这一章先从Spring的IoC开始。
所谓IoC就是一个用XML来定义生成对象的模式,我们看看如果来使用的。
数据模型
1、如下图所示有三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类。
源代码如下:
复制内容到剪贴板
代码:
package.chengang.spring;
publicinterfaceHuman{
voideat();
voidwalk();
}
package.chengang.spring;
publicclassChineseimplementsHuman{
/*(非Javadoc)
*@see.chengang.spring.Human#eat()
*/
publicvoideat(){
System.out.println("中国人对吃很有一套");
}
/*(非Javadoc)
*@see.chengang.spring.Human#walk()
*/
publicvoidwalk(){
System.out.println("中国人行如飞");
}
}
package.chengang.spring;
publicclassAmericanimplementsHuman{
/*(非Javadoc)
*@see.chengang.spring.Human#eat()
*/
publicvoideat(){
System.out.println("美国人主要以面包为主");
}
/*(非Javadoc)
*@see.chengang.spring.Human#walk()
*/
publicvoidwalk(){
System.out.println("美国人以车代步,有四肢退化的趋势");
}
}
2、对以上对象采用工厂模式的用法如下
创建一个工厂类Factory,如下。
这个工厂类里定义了两个字符串常量,所标识不同的人种。
getHuman方法根据传入参数的字串,来判断要生成什么样的人种。
复制内容到剪贴板
代码:
package.chengang.spring;
publicclassFactory{
publicfinalstaticStringCHINESE="Chinese";
publicfinalstaticStringAMERICAN="American";
publicHumangetHuman(Stringethnic){
if(ethnic.equals(CHINESE))
returnnewChinese();
elseif(ethnic.equals(AMERICAN))
returnnewAmerican();
else
thrownewIllegalArgumentException("参数(人种)错误");
}
}
下面是一个测试的程序,使用工厂方法来得到了不同的“人种对象”,并执行相应的方法。
复制内容到剪贴板
代码:
package.chengang.spring;
publicclassClientTest{
publicstaticvoidmain(String[]args){
Humanhuman=null;
human=newFactory().getHuman(Factory.CHINESE);
human.eat();
human.walk();
human=newFactory().getHuman(Factory.AMERICAN);
human.eat();
human.walk();
}
}
控制台的打印结果如下:
3、采用Spring的IoC的用法如下:
在项目根目录下创建一个bean.xml文件
复制内容到剪贴板
代码:
<?
xmlversion="1.0"encoding="UTF-8"?
>
<!
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:
//www.springframework.org/dtd/spring-beans.dtd">
<beans>
<beanid="Chinese"class=".chengang.spring.Chinese"/>
<beanid="American"class=".chengang.spring.American"/>
</beans>
bean.xml的位置如下图,注意不要看花眼把它看成是lib目录下的了,它是在myspring目录下的。
修改ClientTest程序如下:
复制内容到剪贴板
代码:
package.chengang.spring;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
publicclassClientTest{
publicfinalstaticStringCHINESE="Chinese";
publicfinalstaticStringAMERICAN="American";
publicstaticvoidmain(String[]args){
//Humanhuman=null;
//human=newFactory().getHuman(Factory.CHINESE);
//human.eat();
//human.walk();
//human=newFactory().getHuman(Factory.AMERICAN);
//human.eat();
//human.walk();
ApplicationContextctx=newFileSystemXmlApplicationContext("bean.xml");
Humanhuman=null;
human=(Human)ctx.getBean(CHINESE);
human.eat();
human.walk();
human=(Human)ctx.getBean(AMERICAN);
human.eat();
human.walk();
}
}
从这个程序可以看到,ctx就相当于原来的Factory工厂,原来的Factory就可以删除掉了。
然后又把Factory里的两个常量移到了ClientTest类里,整个程序结构基本一样。
再回头看原来的bean.xml文件的这一句:
<beanid="Chinese"class=".chengang.spring.Chinese"/>
id就是ctx.getBean的参数值,一个字符串。
class就是一个类(包名+类名)。
然后在ClientTest类里获得Chinese对象就是这么一句
human=(Human)ctx.getBean(CHINESE);
因为getBean方法返回的是Object类型,所以前面要加一个类型转换。
总结
(1)也许有人说,IoC和工厂模式不是一样的作用吗,用IoC好象还麻烦一点。
举个例子,如果用户需求发生变化,要把Chinese类修改一下。
那么前一种工厂模式,就要更改Factory类的方法,并且重新编译布署。
而IoC只需要将class属性改变一下,并且由于IoC利用了Java反射机制,这些对象是动态生成的,这时我们就可以热插拨Chinese对象(不必把原程序停止下来重新编译布署)
(2)也许有人说,即然IoC这么好,那么我把系统所有对象都用IoC方式来生成。
注意,IoC的灵活性是有代价的:
设置步骤麻烦、生成对象的方式不直观、反射比正常生成对象在效率上慢一点。
因此使用IoC要看有没有必要,我认为比较通用的判断方式是:
用到工厂模式的地方都可以考虑用IoC模式。
(3)在上面的IoC的方式里,还有一些可以变化的地方。
比如,bean.xml不一定要放在项目录下,也可以放在其他地方,比如.chengang.spring包里。
不过在使用时也要变化一下,如下所示:
newFileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");
另外,bean.xml也可以改成其他名字。
这样我们在系统中就可以分门别类的设置不同的bean.xml。
(4)关于IoC的低侵入性。
什么是低侵入性?
如果你用过Struts或EJB就会发现,要继承一些接口或类,才能利用它们的框架开发。
这样,系统就被绑定在Struts、EJB上了,对系统的可移植性产生不利的影响。
如果代码中很少涉及某一个框架的代码,那么这个框架就可以称做是一个低侵入性的框架。
Spring的侵入性很低,Humen.java、Chinese.java等几个类都不必继承什么接口或类。
但在ClientTest里还是有一些Spring的影子:
FileSystemXmlApplicationContext类和ctx.getBean方式等。
现在,低侵入性似乎也成了判定一个框架的实现技术好坏的标准之一。
(5)关于bean.xml的用法
bean.xml的用法还有很多,其中内容是相当丰富的。
假设Chinese类里有一个humenName属性(姓名),那么原的bean.xml修改如下。
此后生成Chinese对象时,“陈刚”这个值将自动设置到Chinese类的humenName属性中。
而且由于singleton为true这时生成Chinese对象将采用单例模式,系统仅存在一个Chinese对象实例。
复制内容到剪贴板
代码:
<?
xmlversion="1.0"encoding="UTF-8"?
>
<!
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:
//www.springframework.org/dtd/spring-beans.dtd">
<beans>
<beanid="Chinese"class=".chengang.spring.Chinese"singleton="true">
<propertyname="humenName">
<value>陈刚</value>
</property>
</bean>
<beanid="American"class=".chengang.spring.American"/>
</beans>
Spring核心技术之Ioc和AOP(2010-03-1215:
21:
29)转载▼标签:
it
一、Spring应用环境的配置:
1.在classpath中添加以下包:
1)SPRING_HOME/dist/spring.jar、
2)SPRING_HOME/lib/jakarta-commons/commons-logging.jar
3)SPRING_HOME/lib/log4j/log4j-1.2.xx.jar
2.在classpath中添加Spring的配置文件:
applicationContext.xml
在SPRING_HOME/samples/jpetstore/war/WEB-INF目录下有样板文件。
二、IoC容器:
1.IoC概念:
反向控制、控制反转。
对象不需要主动去查找依赖类的实例。
而是由其它应用给它注入。
DI:
依赖注入。
2.Spring对IoC的支持:
Spring提供了BeanFactory和ApplicationContext这两种IoC容器,来帮助你管理Bean、Bean之间的依赖关系以及Bean的生命周期。
三、Spring中IoC:
1.Bean装配:
在Spring配置文件中用标记来装配一个Bean.
...
2.用setter方法注入它的依赖类:
1)在Bean中针对依赖类属性添加一个setter方法。
2)在Bean的配置中通过标记的子标记来注入这个属性。
注入的可以是值,也可是容器中另一个Bean的引用。
3.用构造器注入它的依赖类:
4.自动装配:
标记有一个autowire属性来指定自动装配的方式。
建议少用。
1)byName2)byType3)coustructor4)autodetect
5.指定bean的生存范围:
标记有一个scope属性来指定:
1)sigleton:
一个Spring容器一个实例(默认值)
2)prototype:
使用一次就创建一个实例
3)request、session、global-session:
在WebApplicationContext中才有效。
6.指定Bean的初始化和销毁:
使用标记的以下两个属性:
1)init-method
2)destroy-method
7.装配Bean的继承:
使用标记的parent属性来指定它的父类Bean的标识。
默认情况下,父类Bean的属性会使用父类Bean的装配。
子类的属性使用子类的。
可以在子类中对父类的属性进行重新装配。
四、AOP:
面向切面编程
1.AOP:
把交叉功能模块化,把应用服务和业务逻辑完全分离。
2.术语:
a)切面(Aspect):
就是指你要实现的交叉功能。
如:
日志记录、事务管理、安全验证()。
b)连接点(Joinpoint):
应用程序执行过程中可以插入切面的地点。
如某方法调用时或者处理异常时。
Spring只支持方法连接点
c)通知(Advice):
在特定的连接点,AOP框架要执行的动作。
切面的功能被叫做通知。
通知有各种类型,其中包括“around”、“before”和“after”等。
如:
向日志文件写日志、开启事务、提交事务。
d)切入点(Pointcut):
定义了需要注入advice的位置。
通常使用一些表达式来匹配连接点。
e)目标对象(TargetObject):
被一个或者多个切面所通知的对象。
f)代理对象(Proxy):
向目标对象应用通知之后被创建的对象。
g)织入(Weaving):
把切面应用到目标对象来创建新的代理对象的过程。
Spring的切面是在程序运行的某个时刻被织入的。
3.要使用Spring的完整AOP功能,需要添加:
cglib包,AspectJ的包(2个)。
4.配置文件方式实现AOP
1)定义一个切面类。
这个类中定义各个通知方法。
声明到Spring的配置文件中:
config>
--配置一个切面-->
aspectid="logAspect"ref="logAspectBean">
...
aspect>
config>
2)定义切入点:
通过一个AspectJ的切入点表达式来定义选择哪些类的哪些方法需要切入通知。
config>
--配置一个切面-->
aspectid="logAspect"ref="logAspectBean">
--定义切入点-->
pointcutid="allMethod"expression_r="execution(*com.qiujy.service.*.*(..))"/>
...
aspect>
config>
3)声明通知:
config>
--配置一个切面-->
aspectid="logAspect"ref="logAspectBean">
--定义切入点-->
pointcutid="allMethod"expression_r="execution(*com.qiujy.service.*.*(..))"/>
--配置通知-->
beforemethod="start"pointcut-ref="allMethod"/>
after-returningmethod="end"pointcut-ref="allMethod"/>
aftermethod="back"pointcut-ref="allMethod"/>
after-throwingmethod="exception"pointcut-ref="allMethod"/>
aspect>
config>
5.Annotation方式实现AOP
1)配置Spring对AspectJ注解的支持:
aspectj-autoproxy/>
2)使用注解定义切面、切入点、通知:
@Aspect//声明一个切面类
publicclassLogAspect{
privateLoglog=LogFactory.getLog(this.getClass());
//定义了一个切入点(使用表达式来选择连接点)
@Pointcut("execution(*com.qiujy.service.*.*(..))")
privatevoidbbb(){}
//声明前置通知
@Before("execution(*com.qiujy.service.*.add*(..))")
publicvoidstart(JoinPointcall){
StringclassName=call.getTarget().getClass().getName();
StringmethodName=call.getSignature().getName();
log.info(className+"类的"+methodName+"方法开始了");
}
//声明返回后通知
@AfterReturning("bbb()")
publicvoidend(){
log.info("方法正常结束了");
}
//声明方法退出后通知
@After("bbb()")
publicvoidback(){
log.info("方法返回了");
}
//声明异常抛出后通知
@AfterThrowing("bbb()")
publicvoidexception(){
log.info("方法执行出异常了");
}
}
Spring框架中的ioc的幽默解释
责任编辑:
cynthia
作者:
来自ITPUB论坛2008-01-30
文本Tag:
JavaSpring开发语言
【IT168技术文档】IoC就是InversionofControl,控制反转。
在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。
这称为控制反转。
下面我们以几个例子来说明什么是IoC
假设我们要设计一个Girl和一个Boy类,其中Girl有kiss方法,即Girl想要Kiss一个Boy。
那么,我们的问题是,Girl如何能够认识这个Boy?
在我们中国,常见的MM与GG的认识方式有以下几种
1 青梅竹马;2 亲友介绍;
3 父母包办
那么哪一种才是最好呢?
青梅竹马:
Girl从小就知道自己的Boy。
publicclassGirl{
voidkiss(){
Boyboy=newBoy();
}
}
然而从开始就创建的Boy缺点就是无法在更换。
并且要负责Boy的整个生命周期。
如果我们的Girl想要换一个怎么办?
(笔者严重不支持Girl经常更换Boy)
亲友介绍:
由中间人负责提供Boy来见面
publicclassGirl{
voidkiss(){
Boyboy=BoyFactory.createBoy();
}
}
亲友介绍,固然是好。
如果不满意,尽管另外换一个好了。
但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,无处不在,无处不能。
实在是太繁琐了一点,不够灵活。
我为什么一定要这个亲友掺和进来呢?
为什么一定要付给她介绍费呢?
万一最好的朋友爱上了我的男朋友呢?
父母包办:
一切交给父母,自己不用费吹灰之力,只需要等着Kiss就好了。
publicclassGirl{
voidkiss(Boyboy){
//kissboy
boy.kiss();
}
}
Well,这是对Girl最好的方法,只要想办法贿赂了Girl的父母,并把Boy交给他。
那么我们就可以轻松的和Girl来Kiss了。
看来几千年传统的父母之命还真是有用哦。
至少Boy和Girl不用自己瞎忙乎了。
这就是IOC,将对象的创建和获取提取到外部。
由外部容器提供需要的组件。
我们知道好莱坞原则:
“Donotcallus,wewillcallyou.”意思就是,You,girlie,donotcalltheboy.Wewill