![火龙果Spring框架教学课件ppt_第1页](http://file4.renrendoc.com/view/9d06fbc59ec6812010c9686103e92157/9d06fbc59ec6812010c9686103e921571.gif)
![火龙果Spring框架教学课件ppt_第2页](http://file4.renrendoc.com/view/9d06fbc59ec6812010c9686103e92157/9d06fbc59ec6812010c9686103e921572.gif)
![火龙果Spring框架教学课件ppt_第3页](http://file4.renrendoc.com/view/9d06fbc59ec6812010c9686103e92157/9d06fbc59ec6812010c9686103e921573.gif)
![火龙果Spring框架教学课件ppt_第4页](http://file4.renrendoc.com/view/9d06fbc59ec6812010c9686103e92157/9d06fbc59ec6812010c9686103e921574.gif)
![火龙果Spring框架教学课件ppt_第5页](http://file4.renrendoc.com/view/9d06fbc59ec6812010c9686103e92157/9d06fbc59ec6812010c9686103e921575.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Spring企业开发
Spring是什么Spring是一个开源的控制反转(InversionofControl,IoC)和面向切面(AOP)的容器框架.它的主要目的是简化企业开发.IOC控制反转publicclassPersonService{//服务层
privatePersonDaopersonDao=new
PersonDaoBean();
publicvoidsave(Personperson){//保存一个对象personDao.save(person);}}PersonDaoBean是在应用内部创建及维护的(在PersonService类中new出来的)。所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。依赖注入(DependencyInjection)当我们把依赖对象交给外部容器负责创建,那么PersonService类可以改成如下:publicclassPersonService{
privatePersonDaopersonDao;
//通过构造器参数,让容器把创建好的依赖对象注入进PersonService,当然也可以使用setter方法进行注入。
publicPersonService(PersonDaopersonDao){this.personDao=personDao;}
publicvoidsave(Personperson){personDao.save(person);}}所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。为何要使用Spring在项目中引入spring立即可以带来下面的好处降低组件之间的耦合度,实现软件各层之间的解耦。
可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。容器提供单例模式支持,开发人员不再需要自己编写实现代码。容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。容器提供的众多辅作类,使用这些类能够加快应用的开发,如:JdbcTemplate、HibernateTemplate。Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。ControllerServiceDAO使用Spring的好处当使用spring时,我们可以使用容器提供的众多服务
如果使用Spring,我们就不再需要手工控制事务publicvoidsavePerson(){Peoplepeople=newPeople();people.setCardNo();people.setName("李四");try{ session.save(people); mit();}catch(HibernateExceptione){ transaction.rollback(); e.printStackTrace();}}使用Hibernate框架需要手工提交事务另外,如果使用spring,我们也不需要处理复杂的事务传播行为publicvoidpayment(){Bean1.update();//更新金额Bean2.save();//记录操作日志}如果我们不使用Spring,针对下面这两种业务需求,我们该如何做?第1种可能的业务需求:要求Bean1.update()和Bean2.save()在同一个事务中执行。第2种可能的业务需求:要求不管Bean1.update()的事务是否成功,都需要记录操作日志。publicclassBean1{
publicvoidupdate(){//注意:下面省略了一些代码 Connectionconn=null; conn.setAutoCommit(false);
Statement.executeUpdate(“updateaccountsetamount=?whereid=?");
}}publicclassBean2{
publicvoidsave(){//注意:下面省略了一些代码 Connectionconn=null; conn.setAutoCommit(false);
Statement.executeUpdate(“insertintoLog(content)values(?)");
}}使用Spring,不再需要我们处理复杂的事务传播行为使用Spring,我们只需要通过声明式的事务属性配置就可以轻松地实现这两种业务需求1.要求Bean1.update()和Bean2.save()的在同一个事务中执行2.要求不管Bean1.update()的事务是否成功,都需要记录日志。@Transactional(propagation=Propagation.Required)publicvoidpayment(){Bean1.update();//更新金额Bean2.save();//记录日志}
publicclassBean1{@Transactional(propagation=Propagation.Required)
publicvoidupdate(){
executeUpdate(“updateaccountsetamount=?whereid=?");
}}publicclassBean2{
@Transactional(propagation=Propagation.RequiresNew)
publicvoidsave(){ executeUpdate(“insertintoLog(content)values(?)");}}轻量级与重量级概念的划分经常会有同学问到spring属于轻量级框架,还是重量框架?其实划分一个应用是否属于轻量级还是重量级,主要看它使用了多少服务.使用的服务越多,容器要为普通java对象做的工作就越多,必然会影响到应用的发布时间或者是运行性能.对于spring容器,它提供了很多服务,但这些服务并不是默认为应用打开的,应用需要某种服务,还需要指明使用该服务,如果应用使用的服务很少,如:只使用了spring核心服务,那么我们可以认为此时应用属于轻量级的,如果应用使用了spring提供的大部分服务,这时应用就属于重量级。目前EJB容器就因为它默认为应用提供了EJB规范中所有的功能,所以它属于重量级。使用Spring需要的jar到/download下载spring,然后进行解压缩,在解压目录中找到下面jar文件,拷贝到类路径下dist\spring.jarlib\jakarta-commons\commons-logging.jar如果使用了切面编程(AOP),还需要下列jar文件lib/aspectj/aspectjweaver.jar和aspectjrt.jarlib/cglib/cglib-nodep-2.1_3.jar如果使用了JSR-250中的注解,如@Resource/@PostConstruct/@PreDestroy,还需要下列jar文件lib\j2ee\common-annotations.jar本次课程使用的Spring版本是2.5使用myeclipse添加Spring应用第一步:创建web工程(其实普通j2se工程也可以)使用myeclipse添加Spring应用第二步:在web工程中添加Spring框架支持使用myeclipse添加Spring应用这里只是简单应用,没有涉及到和其它框架的集成,因此选择前面两个就可以了。使用myeclipse添加Spring应用这步的目的是生成Spring配置文件applicationContext.xml文件位置是src使用myeclipse添加Spring应用框架添加完成之后的效果使用myeclipse添加Spring应用publicclassUserInfo{privateIntegerid;privateStringname;privateStringaddress;privateIntegerage;//setandgetmethod……}第三步:创建一个实体类;并生成属性对应的set/get方法使用myeclipse添加Spring应用第四步:根据左边的实体类属性名称和数据类型在Spring配置文件中配置一个bean;这个bean的id值是userInfoBean这个id属性名称对应的值在applicationContext.xml必须是唯一;不能存在同名;在应用程序中将根据id名称来获取这个bean使用myeclipse添加Spring应用//编写测试类,从Spring容器中获取userInfoBeanpackage.chongking;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassBeanUtil{publicstaticvoidmain(String[]args){ ApplicationContextcontext= newClassPathXmlApplicationContext("applicationContext.xml"); UserInfouserInfo=(UserInfo)context.getBean(“normalBean"); System.out.println(userInfo.getName()+":"+userInfo.getAddress());}}第五步:编写测试类;从spring容器中根据bean的id获取bean对象userInfoBean是applicationContext.xml配置文件中的beanid属性值applicationContext.xml<beanid="normalBean"class=".chongking.UserInfo"><propertyname="id"value="1"/><propertyname="name"value="李四"/><propertyname="address"value="柳州"/><propertyname="age"value="22"/></bean>使用eclipse添加Spring应用使用eclipse开发Spring应用需要自己添加使用到的jar文件和spring配置文件(applicationContext.xml)其它的配置和测试跟使用myeclipse是一样的。在java体系中绝大部分的框架应用所涉及到的引用基本上都是jar文件和配置文件。Jar文件和配置文件有多种渠道可以获取;可以从官方网站上下载;可以使用别人现有的;可以通过其它渠道获取。spring的配置文件模版<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd">
</beans>该配置模版可以从spring的参考手册或spring的例子中得到。配置文件的取名可以任意,文件可以存放在任何目录下,但考虑到通用性,一般放在类路径下。编写spring配置文件时,不能出现帮助信息由于spring的schema文件位于网络上,如果机器不能连接到网络,那么在编写配置信息时候就无法出现提示信息,解决方法有两种:1。让机器上网,eclipse会自动从网络上下载schema文件并缓存在硬盘上。2。手动添加schema文件,方法如下:windwos->preferences->myeclipse->filesandeditors->xml->xmlcatalog点"add",在出现的窗口中的KeyType中选择URI,在location中选"Filesystem",然后在spring解压目录的dist/resources目录中选择spring-beans-2.5.xsd,回到设置窗口的时候不要急着关闭窗口,应把窗口中的KeyType改为Schemalocation,Key改为/schema/beans/spring-beans-2.5.xsd实例化spring容器实例化Spring容器常用的两种方式:方法一:在类路径下寻找配置文件来实例化容器ApplicationContextctx=newClassPathXmlApplicationContext(newString[]{"beans.xml"});方法二:在文件系统路径下寻找配置文件来实例化容器ApplicationContextctx=newFileSystemXmlApplicationContext(newString[]{“d:\\beans.xml“});Spring的配置文件可以指定多个,可以通过String数组传入。从spring容器中得到bean当spring容器启动后,因为spring容器可以管理bean对象的创建,销毁等生命周期,所以我们只需从容器直接获取Bean对象就行,而不用编写一句代码来创建bean对象。从容器获取bean对象的代码如下:ApplicationContextctx=newClassPathXmlApplicationContext(“beans.xml”);OrderServiceservice=(OrderService)ctx.getBean("personService");使用dom4j读取spring配置文件publicclassClassPathXmlApplicationContext{
privateList<BeanDefinition>beanDefines=newArrayList<BeanDefinition>();
publicApplicationContext(Stringfilename){ init(filename);}
privatevoidinit(Stringfilename){SAXReadersaxReader=newSAXReader();Documentdocument=null;try{URLxmlpath=this.getClass().getClassLoader().getResource(filename);document=saxReader.read(xmlpath);Map<String,String>nsMap=newHashMap<String,String>();nsMap.put("ns","/schema/beans");//加入命名空间
XPathxsub=document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element>beans=xsub.selectNodes(document);//获取文档下所有bean节点
for(Elementelement:beans){Stringid=element.attributeValue("id");//获取id属性值
Stringclazz=element.attributeValue("class");//获取class属性值
BeanDefinitionbeanDefine=newBeanDefinition(id,clazz);beanDefines.add(beanDefine);}}catch(Exceptione){e.printStackTrace();}}}三种实例化bean的方式-使用类构造器实例化//实体类设计publicclassUserInfo{privateIntegerid;privateStringname;privateStringaddress;privateIntegerage;//构造子publicUserInfo(){}//构造子publicUserInfo(Integerid,Stringname, Stringaddress,Integerage){ this.id=id; =name; this.address=address; this.age=age;}//setandgetmethod…}applicationContext.xml配置<beanid="normalBean" class=".chongking.UserInfo"> <propertyname="id"value="1"/> <propertyname="name"value="李四"/> <propertyname="address"value="柳州"/> <propertyname="age"value="22"/></bean>//从Spring容器获取Bean测试代码publicvoidgetUserInfo(){ UserInfouserInfo= (UserInfo)context.getBean("normalBean"); System.out.println(userInfo.getId()+": "+userInfo.getName()+":"+userInfo.getAddress());}三种实例化bean的方式-使用静态工厂方法实例化//工厂类设计publicclassBeanFactory{publicstaticUserInfofactoryDao(){returnnewUserInfo(1,"王五","南宁",21);}}applicationContext.xml配置<beanid="staticFactoryBean" class=".chongking.BeanFactory"
factory-method="factoryDao"/>publicvoidstaticFactoryBean(){//测试代码 UserInfouserInfo=(UserInfo)context.getBean("staticFactoryBean"); System.out.println(userInfo.getId()+": "+userInfo.getName()+":"+userInfo.getAddress());}//实体类设计publicclassUserInfo{privateIntegerid;privateStringname;privateStringaddress;privateIntegerage;//构造子publicUserInfo(){}//构造子publicUserInfo(Integerid,Stringname, Stringaddress,Integerage){ this.id=id; =name; this.address=address; this.age=age;}//setandgetmethod…}三种实例化bean的方式-使用实例工厂方法实例化//工厂类设计publicclassBeanFactory{publicUserInfocreateUserInfo(){returnnewUserInfo(1,"王五","南宁",21);}}applicationContext.xml配置<beanid="factoryBean"class=".chongking.BeanFactory"/><beanid="instanceFactoryBean"factory-bean="factoryBean"factory-method="createUserInfo"/>//使用实例工厂方法实例化测试publicvoidinstanceFactoryBean(){UserInfouserInfo=(UserInfo)context.getBean("instanceFactoryBean");System.out.println(userInfo.getId()+":"+userInfo.getName()+":"+userInfo.getAddress());}Bean的作用域(scope属性).singleton
在每个SpringIoC容器中一个bean定义只有一个对象实例。默认情况下会在容器启动时初始化bean,但我们可以指定Bean节点的lazy-init=“true”来延迟初始化bean,这时候,只有第一次获取bean会才初始化bean。如:
<beanid="xxx"class=".chongking.OrderServiceBean"lazy-init="true"/>如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true“,如下:<beansdefault-lazy-init="true“...>可以通过在构造函数中输出信息来跟踪.prototype
每次从容器获取bean都是新的对象。.request.session.globalsessionrequest,session,globalsession是针对web程序而言的指定Bean的初始化方法和销毁方法指定Bean的初始化方法和销毁方法<beanid="xxx"class=".chongking.OrderServiceBean"init-method="init"destroy-method="close"/>importorg.junit.*;importorg.springframework.context.support.AbstractApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassBeanUtil{AbstractApplicationContextcontext=null;//Spring容器对象(注意:不是ApplicationContext)@Beforepublicvoidbefore(){System.out.println("before...");context=newClassPathXmlApplicationContext("applicationContext.xml");}@TestpublicvoidgetEmployeeBean(){
//Employee类中有两个方法:init();和close()Employeeemployee=(Employee)context.getBean("empBean");System.out.println(employee.getName());}@Afterpublicvoidafter(){
context.close();//需要显示调用}}注入依赖对象-基本类型对象注入<beanid="empBean"class=".chongking.Employee"><propertyname="id"value="1"/><propertyname="name"value="李四"/><propertyname="address"value="柳州"/></bean>publicclassEmployee{//实体类设计privateIntegerid;privateStringname;privateStringaddress;publicEmployee(){System.out.println("不带参数的构造方法");}publicEmployee(Integerid,Stringname,Stringaddress){System.out.println("带参数构造函数");this.id=id;=name;this.address=address;}//setandgetmethod注入依赖对象-构造器注入applicationContext.xml配置<beanid="empBean"class=".chongking.Employee"><constructor-argindex="0"type="java.lang.Integer"value="1"/><constructor-argindex="1"type="java.lang.String"value="李四"/><constructor-argindex="2"type="java.lang.String"value="桂林"/></bean>实体类构造方法publicEmployee(Integer
id,String
name,String
address){System.out.println("带参数构造函数");this.id=id;=name;this.address=address;}@TestpublicvoidgetEmployeeBean(){//测试方法Employeeemployee=(Employee)context.getBean("empBean");System.out.println(employee.getId()+":"+employee.getName()+":"+employee.getAddress());}注入依赖对象-注入其它Bean-1applicationContext.xml配置<beanid="cpuBean"class=".chongking.Cpu"/><beanid="computerBean"class=".chongking.Computer"><propertyname="cpu"ref="cpuBean"/></bean>publicclassCpu{publicvoidhardwareInfo(){System.out.println("AMD速龙");}}@TestpublicvoidgetComputer(){//测试类
Computercomputer=
(Computer)context.getBean("computerBean");
computer.testCput();}publicclassComputer{privateCpucpu;//set方法是必须的(set注入)publicvoidsetCpu(Cpucpu){this.cpu=cpu;}publicCpugetCpu(){returncpu;}publicvoidtestCput(){cpu.hardwareInfo();}}注入依赖对象-注入其它Bean-2applicationContext.xml配置<beanid="computerBean"class=".chongking.Computer"><propertyname="cpu"><beanclass=".chongking.Cpu"/></property></bean>publicclassCpu{publicvoidhardwareInfo(){System.out.println("AMD速龙");}}@TestpublicvoidgetComputer(){//测试类
Computercomputer=
(Computer)context.getBean("computerBean");
computer.testCput();}publicclassComputer{privateCpucpu;//set方法是必须的(set注入)publicvoidsetCpu(Cpucpu){this.cpu=cpu;}publicCpugetCpu(){returncpu;}publicvoidtestCput(){cpu.hardwareInfo();}}使用内部bean,但该bean不能被其他bean使用练习-通过Bean注入模拟计算机组装//接口设计publicinterfaceUSB{//USB接口信息publicvoidinfo(Stringcontent);}publicinterfaceIprint{//打印机接口信息publicvoidinfo(Stringcontent);}publicclassMemory{//内存类publicvoidinfo(Stringconfig){System.out.println("内存配置:"+config);}}publicclassComputer{//计算机类privateUSBusb;privateIprintprint;privateMemorymemory;publicvoidshowHardWareInfo(){("移动硬盘");("彩色打印机");("金士顿内存条");}//省略了set、get方法}applicationContext.xml配置<beanid="uDisk"class="puter.UDisk"/><beanid="colorPrint"class="puter.ColorPrint"/><beanid="memory"class="puter.Memory"/><beanid="computerBean"class="puter.Computer"><propertyname="usb"ref="uDisk"/><propertyname="print"ref="colorPrint"/><propertyname="memory"ref="memory"/></bean>@TestpublicvoidgetComputer(){//模拟计算机组装测试方法Computercomputer=(Computer)context.getBean("computerBean");computer.showHardWareInfo();}//接口实现类publicclassUDiskimplementsUSB{publicvoidinfo(Stringconfig){System.out.println("usb接口配置:"+config);}}publicclassColorPrintimplementsIprint{publicvoidinfo(Stringconfig){System.out.println("彩色打印机:"+config);}}集合类型的装配<beanid="order"class=".chongking.Order"><propertyname="lists"><list><value>cjkj</value></list></property> <propertyname="sets"><set><value>set</value></set></property> <propertyname="maps"><map><entrykey=“lisi"value="28"/></map></property> <propertyname="properties"><props> <propkey="12">cjkj</prop></props></property></bean>@TestpublicvoidgetOrder(){//测试类Orderorder=(Order)context.getBean("order");List<String>lists=order.getLists();for(Strings:lists){System.out.println(s);}}publicclassOrder{privateSet<String>sets=newHashSet<String>();privateList<String>lists=newArrayList<String>();privatePropertiesproperties=newProperties();privateMap<String,String>maps=newHashMap<String,String>();//这里省略属性的getter和setter方法}依赖注入使用构造器注入使用属性setter方法注入使用Field注入(用于注解方式)注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。1.手工装配依赖对象2.自动装配依赖对象依赖注入--手工装配手工装配依赖对象,在这种方式中又有两种编程方式1.在xml配置文件中,通过在bean节点下配置,如<beanid="orderService"class=".chongking.People"><constructor-argindex=“0”type=“java.lang.Integer”value=“1”/>//构造器注入(带参构造函数第1个值)
<constructor-argindex=“1”type=“java.lang.String”value=“李四”/>//构造器注入(带参构造函数第2个值)<constructor-argindex=“2”type=“java.lang.String”value=“柳州”/>//构造器注入(带参构造函数第3个值)
<propertyname=“name”value=“李四”/>//属性setter方法注入</bean>2.在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在xml配置文件中配置以下信息:<beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"
xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd
/schema/context/schema/context/spring-context-2.5.xsd">
<context:annotation-config/></beans>这个配置隐式注册了多个对注释进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor注:@Resource注解在spring安装目录的lib\j2ee\common-annotations.jar依赖注入--手工装配在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
@AutowiredprivatePersonDaopersonDao;//用于字段上@AutowiredpublicvoidsetOrderDao(OrderDaoorderDao){//用于属性的setter方法上this.orderDao=orderDao;}@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false@Autowired(required=false)。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:@Autowired@Qualifier("personDaoBean")privatePersonDaopersonDao;@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resource(name=“personDaoBean”)privatePersonDaopersonDao;//用于字段上注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。依赖注入--手工装配-注解装配AutowiredpublicclassComputer{//计算机类
@AutowiredprivateUSBusb;
@AutowiredprivateIprintprint;
@AutowiredprivateMemorymemory;publicvoidshowHardWareInfo(){("移动硬盘");("彩色打印机");("金士顿内存条");}//不用再写set、get方法}bean.xml配置<beanid="uDisk"class="puter.UDisk"/><beanid="colorPrint"class="puter.ColorPrint"/><beanid="memory"class="puter.Memory"/><beanid="computerBean"class="puter.Computer"><!–
不用再配置computerBean中引用的bean<propertyname="usb"ref="uDisk"/><propertyname="print"ref="colorPrint"/><propertyname="memory"ref="memory"/>--></bean>@TestpublicvoidgetComputer(){//模拟计算机组装测试方法Computercomputer=(Computer)context.getBean("computerBean");computer.showHardWareInfo();}与xml配置文件中配置引用的Bean的区别是:ComputerBean中不用再配置引用的Bean;这是优点;缺点是还是要在spring配置文件中配置uDisk,colorPrint,memory,computerBean这些Bean依赖注入--手工装配-注解装配ResourcepublicclassComputer{privateUSBusb;privateIprintprint;privateMemorymemory;publicvoidshowHardWareInfo(){
("移动硬盘");
("彩色打印机");
("金士顿内存条");}@Resource(name="uDisk")publicvoidsetUsb(USBusb){
this.usb=usb;}@Resource(name="colorPrint")publicvoidsetPrint(Iprintprint){
this.print=print;}@Resource(name="memory")publicvoidsetMemory(Memorymemory){
this.memory=memory;}
//不用再写set、get方法}bean.xml配置<beanid="uDisk"class="puter.UDisk"/><beanid="colorPrint"class="puter.ColorPrint"/><beanid="memory"class="puter.Memory"/><beanid="computerBean"class="puter.Computer"><!--不用再配置computerBean中引用的bean<propertyname="usb"ref="uDisk"/><propertyname="print"ref="colorPrint"/><propertyname="memory"ref="memory"/>--></bean>@TestpublicvoidgetComputer(){//模拟计算机组装测试方法Computercomputer=(Computer)context.getBean("computerBean");computer.showHardWareInfo();}与xml配置文件中配置引用的Bean的区别是:ComputerBean中不用再配置引用的Bean;这是优点;缺点是还是要在spring配置文件中配置uDisk,colorPrint,memory,computerBean这些Bean依赖注入--自动装配依赖对象对于自动装配,大家了解一下就可以了,实在不推荐大家使用。例子:<beanid="..."class="..."autowire="byType"/>autowire属性取值如下:byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null。byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null。constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。通过在classpath自动扫描方式把组件纳入spring容器中管理前面的例子我们都是使用XML的bean定义来配置组件。在一个稍大的项目中,通常会有上百个组件,如果这些这组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找及维护起来也不太方便。spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息:<beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"
xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd
/schema/context/schema/context/spring-context-2.5.xsd"><context:component-scanbase-package=".chongking"/></beans>其中base-package为需要扫描的包(含子包)。@Service用于标注业务层组件、@Controller用于标注控制层组件(如struts中的action)、@Repository用于标注数据访问组件,即DAO组件。而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。自动扫描式注入Bean(优点:配置文件中不用再配置bean)//接口设计publicinterfaceUSB{//USB接口信息publicvoidinfo(Stringcontent);}publicinterfaceIprint{//打印机接口信息publicvoidinfo(Stringcontent);}@Component("memory")publicclassMemory{//内存类publicvoidinfo(Stringconfig){System.out.println("内存配置:"+config);}}@Component("computer")publicclassComputer{//面向接口编程,下面的组件都是接口,不是类@Resource(name="usb")privateUSBusb;@Resource(name="colorPrint")privateIprintprint;@Resource(name="memory")privateMemorymemory;publicvoidshowHardWareInfo(){("移动硬盘");("彩色打印机");("金士顿内存条");}//上面的注解类也可以写在set方法上面//不用再写set、get方法}Spring配置文件配置<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:p="/schema/p"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd"><context:component-scanbase-package=".chongking"/></beans>@TestpublicvoidgetComputer(){Computercomputer=(Computer)context.getBean("computer");computer.showHardWareInfo();}@Component(value="usb")publicclassUDiskimplementsUSB{//接口实现类publicvoidinfo(Stringconfig){System.out.println("usb接口配置:"+config);}}@Component("colorPrint")publicclassColorPrintimplementsIprint{publicvoidinfo(Stringconfig){System.out.println("彩色打印机:"+config);}}静态代理//接口设计publicinterfaceAnimal{publicabstractvoideat(Stringfood);publicabstractStringtype();}//AnimalWrapper类是包装类(代理类)publicclassAnimalWrapper{privateAnimalanimal;publicAnimalWrapper(Animalanimal){this.animal=animal;}publicvoideat(Stringfood){System.out.println("+++Wrapped前置通知!+++");animal.eat(food);System.out.println("+++Wrapped后置通知!+++");}publicStringtype(){System.out.println("WrappedBefore!");Stringtype=animal.type();System.out.println("WrappedAfter!");returntype;}}publicclassMonkeyimplementsAnimal{//接口实现类publicStringtype(){Stringtype="哺乳动物";System.out.println(type);returntype;}publicvoideat(Stringfood){System.out.println("Thefoodis"+food+"!");}}@Testpublicstaticvoidmain(String[]args){AnimalWrapperwrapper=newAnimalWrapper(newMonkey());wrapper.eat("香蕉");}静态代理的缺点前面我们通过包装的模式完成了对Animal所有子类的静态代理,在代理方法中,你可以加入一些自己的额外的处理逻辑,就像上面的控制台输出语句一样。那么Spring的前置、后置、环绕方法通知,通过这种方式可以有限的模拟出来,以Spring的声明式事务为例,无非就是在调用包装的目标方法之前处开启事务,在之后提交事务,这样原有的业务逻辑没有受到任何事务管理代码的侵入。这种方式的静态代理,缺点就是当Animal接口中增加了新的方法,那么包装类中也必须增加这些新的方法。JDK动态代理publicclassJDKProxyimplements
InvocationHandler{
private
ObjecttargetObject;//要代理的目标对象
public
ObjectcreateProxyInstance(ObjecttargetObject){
this.targetObject=targetObject;/**第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器*第二个参数设置代理类实现的接口*第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法*/
return
Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
this.targetObject.getClass().getInterfaces(),this); }
//method是被拦截到的方法,args是该方法所需要传的参数
public
Objectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
returnmethod.invoke(this.targetObject,args);//把方法调用委派给目标对象
}}当目标类实现了接口,我们可以使用jdk的Proxy来生成代理对象。JDK动态代理案例:/***业务接口*@authorAdministrator*/publicinterfaceILogin{
publicbooleanlogin(StringipAddress,Stringname,Stringpassword);}/***目标类(接口实现类)*@authorAdministrator**/publicclassLoginImplimplementsILogin{
publicbooleanlogin(StringipAddress,Stringname,Stringpassword){
System.out.println("进入目标类的方法");
System.out.println(LoginImpl.class.getName()+"用户:"+name+"在"+ipAddress+"登录");
returntrue;}}代理类在后面JDK动态代理案例(续)-代理类publicclassJDKProxyimplementsInvocationHandler{privateObjecttargetObject;//要代理的目标对象publicObjectcreateProxyInstance(ObjecttargetObject){//创建代理对象this.targetObject=targetObject;//赋值,下面invoke方法用到这个对象/**参数1:设置代码使用的类装载器,一般采用跟目标类相同的类装载器*参数2:设置代理类实现的接口*参数3:设置回调对象,当代理对象的方法被调用时(这里对应的是LoginImpl类中的login方法),会委派给该参数指定对象的invoke方法*/ObjectproxyInstance=Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);returnproxyInstance;}//通知的概念就是要实现某个功能(这个方法就是环绕通知:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个体家装合同范本
- 共享单车包租合同范本
- 农村地基出让合同范本
- 个人打井售卖合同范本
- 产品加工合同范本模板
- 共享茶馆入股合同范本
- 个人他权合同范本
- epc 垫资合同范本
- 农村木板出售合同范本
- 以合同范本为准
- 新部编版小学六年级下册语文第二单元测试卷及答案
- 5《这些事我来做》(说课稿)-部编版道德与法治四年级上册
- 2025年福建福州市仓山区国有投资发展集团有限公司招聘笔试参考题库附带答案详解
- 2025年广东省深圳法院招聘书记员招聘144人历年高频重点提升(共500题)附带答案详解
- 2025年人教版新教材数学一年级下册教学计划(含进度表)
- GB/T 45107-2024表土剥离及其再利用技术要求
- 2025长江航道工程局招聘101人历年高频重点提升(共500题)附带答案详解
- 一年级家长会课件2024-2025学年
- 五年级上册脱式计算100题及答案
- 新版北师大版小学3三年级数学下册全册教案完整(新教材)
- 【说课】安史之乱与唐朝衰亡
评论
0/150
提交评论