第十九章spring的依赖注入及aop详解_第1页
第十九章spring的依赖注入及aop详解_第2页
第十九章spring的依赖注入及aop详解_第3页
第十九章spring的依赖注入及aop详解_第4页
第十九章spring的依赖注入及aop详解_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第十九章spring的依赖注入及Aop详解理论部分本章目标掌握Spring的三种注入方式掌握用ref的属性指定依赖的3种模式理解集合的注入方式了解自动装配的五种模式了解Spring中的AOP使用ProxyFactoryBean创建AOP代理了解spring中AOP的三种代理方式理解Spring的事务处理掌握使用spring管理Hibernate依赖注入的三种方式依赖注入的意义

让组件依赖于抽象,当组件要与其他实际对象发生依赖关系时,通过抽象来注入依赖的实际对象。依赖注入的三种方式

接口注入、SET注入、构造器注入接口注入

接口注入指的就是在接口的定义中要注入的信息,并通过接口完成注入。接口注入的方式接口注入的具体步骤(1)编写接口

publicinterfaceMyTestBean{ publicStringmyaction(); }(2)编写类实现此接口publicclassMyTestAction1implementsMyTestBean{ privateStringcname; publicStringmyaction(){ //将得到的属性转换为大写 returncname.toUpperCase(); } publicStringgetCname(){ returncname; } publicvoidsetCname(Stringcname){ ame=cname; }}接口注入的方式—配置bean到xml文件中编写spring的配置文件,配置bean的信息<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns=""xmlns:xsi=""xsi:schemaLocation="/spring-beans-2.0.xsd">

<!--id用来唯一表示该bean,class用来表示该bean的来源--> <beanid="myaction1"class="com.bean.MyTestAction1"> <!-通过依赖注入完成属性的赋值- <propertyname="cname"> <value>zhangsan</value> </property> </bean></beans>接口注入的方式—编写测试public

classUseActionClass{public

static

voidmain(String[]args){//获取xml文件所在的路径Stringpath=UseActionClass.class.getClass().getResource("/").getPath();//初始化上下文关系ApplicationContextctx=newFileSystemXmlApplicationContext(path+"/applicationContext.xml");//通过spring配置文件获取bean的对象,并有父类来接受MyTestBeanmybean=(MyTestBean)ctx.getBean("myaction1");//获取接口中的方法Strings=mybean.myaction();//打印测试的结果System.out.println(s);}}接口注入的原则在接口注入中,定义的接口必须通过实现类来完成。在测试类中,通过ApplicationContext对象来呼叫bean的实现,并传递给父类。若要改变其方法,只需要将子类注入进xml文件中进行组装, 让组件依赖于抽象,当组件要与其他实际对象发生依赖关系时,通过抽象来注入依赖的实际对象。SET注入方式Set注入指的是在接受注入的类中定义一个set方法,并在参数中定义需要注入的元素实现的步骤编写具有set方法的类public

classMyclass{privateStringmystr;public

voidsetMystr(Stringmystr){this.mystr=mystr;}publicStringgetStr(){return

mystr;}}Set注入配置文件的编写<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns=""xmlns:xsi=""xsi:schemaLocation="/spring-beans-2.0.xsd"><!--id用来唯一表示该bean,class用来表示该bean的来源--><beanid="myclass1"class="com.bean.Myclass"/></beans>Set的测试代码public

classUseMyClass{public

static

voidmain(String[]args){//获取xml文件所在的路径String path=UseActionClass.class.getClass().getResource("/").getPath();//初始化上下文关系ApplicationContextctx=newFileSystemXmlApplicationContext(path+"/myspring.xml");//通过spring配置文件获取bean的对象,并有父类来接受Myclassmybean=(Myclass)ctx.getBean("myclass1");mybean.setMystr("set注入成了!");System.out.println(mybean.getStr());}}运行结果:

log4j:WARNNoappenderscouldbefoundforlogger(org.springframework.context.support.FileSystemXmlApplicationContext).log4j:WARNPleaseinitializethelog4jsystemproperly.set注入成了!构造器的注入构造器的注入就是在接受注入的类中定义一个构造方法,并在参数中定义需要注入的元素编写带有构造器的类,并传递需要注入的元素public

classMyClass2{privateStringstr;publicMyClass2(Stringmystr){str=mystr;}publicStringgetStr(){return

str;}}在配置文件中注入类<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns=""xmlns:xsi=""xsi:schemaLocation="/spring-beans-2.0.xsd"><!--id表识bean的名称,class指出类的来源--><beanid="myclass2"class="com.bean.Myclass2"><!--说明给第几个构造器传递参数,进行注入--><constructor-argindex="0"><value>HELLOWORLD</value></constructor-arg></bean></beans>构造器注入的测试类public

classUseClass2{public

static

voidmain(String[]args){//获取xml文件所在的路径Stringpath=UseActionClass.class.getClass().getResource("/").getPath();//初始化上下文关系ApplicationContextctx=newFileSystemXmlApplicationContext(path+"/myspring2.xml");//通过spring配置文件获取bean的对象,并有父类来接受MyClass2mybean=(MyClass2)ctx.getBean("myclass2");//获取接口中的方法Strings=mybean.getStr();//打印测试的结果System.out.println(s);}}ref的属性指定依赖—Bean属性指定用ref元素的bean属性指定被参考指定引用的BEAN是spring中最常见的形式,它允许被指向的bean可以在同一个xml文件中,也可以不再同一个xml文件中。

Spring1.xml文件

<?xmlversion="1.0"encoding="UTF-8"?><beans…………><!--id表识bean的名称,class指出类的来源--><beanid="loginbean"class="com.bean.LoginBean"/></beans>--spring2.xml文件

<beans………….><!--id表识bean的名称,class指出类的来源--><beanid="logindao"class="com.bean.LoginDao"><propertyname="login"><refbean="loginbean"/></property></bean></beans>集合的注入方式—List注入方式集合类型的注入方式

当类中存在集合类型的属性,采用的一种注入机制。编写带有List属性的类,并将其注入到spring的配置文件中。publicclassListBean{ privateListls; publicListgetLs(){ returnls; } publicvoidsetLs(Listls) { this.ls=ls; }}<beanid="mylist"class="com.bean.ListBean"><propertyname="ls"><list><value>aa</value><value>bb</value><value>cc</value></list></property></bean>下面是测试代码

//通过spring配置文件获取bean的对象ListBeanmybean=(ListBean)ctx.getBean("mylist");Listls=mybean.getLs();for(inti=0;i<ls.size();i++){System.out.println(ls.get(i));}集合的注入方式—Set注入方式<beanid="mylist"class="com.bean.ListBean"><propertyname="ls"><set><value>aa</value><value>bb</value><value>cc</value></set></property></bean>集合的注入方式—Map注入方式<beanid="mylist"class="com.bean.ListBean"><propertyname="ls"><map><entrykey="1"><value>技术部</value></entry><entrykey="2"><value>财务部</value></entry><entrykey="3"><value>市场部</value></entry></map></property></bean>集合的注入方式—Properties注入方式<beanid="mylist"class="com.bean.ListBean"><propertyname="ls"><props><propkey="1">技术部</prop><propkey="2">财务部</prop><propkey="3">市场部</prop></props></property></bean>自动装配的五种模式Byname模式

通过bean的属性名称自动装配Bytype模式

如果配置文件中正好有一个与属性类型一样的bean,就自动装配这个属性Constructor模式

根据构造函数的参数进行自动装配。\Autodetect

通过对bean检查类的内部来选择Constructor或者bytype,如果没有构造器,就用bytype(根据类型)装配,有构造器,就先使用构造器装配。Spring中的AOPAOP(AspectOrientedProgramming)面向方面的编程。他使程序员可以更好的将本不该彼此粘合在一起的功能分离开。AOP是一种思想,他和具体的实现技术无关。任何一种符合AOP思想的技术实现都可看作AOP的实现。它主要用于和业务关系不大的代码,例如日志、权限、异常、事务处理等等。使用AOP就不用在业务逻辑中实现与业务功能关系不大的代码,从而降低了代码的耦合性,从而达到易于维护和重用的目的。ProxyFactoryBean创建AOP代理proxyFactoryBean的主要功能在于代理目标类的所有方法。也可以理解为对接口的代理。代理方式如下:首先编写操作接口public

interfaceDaoInterface{ public

booleansave(Objectob); public

booleanupdate(Objectob); public

booleandel(Stringid); publicObjectfindById(Stringid); publicVectorfindAll();}ProxyFactoryBean创建AOP代理编写业务接口的实现类public

classEmpDaoimplementsDaoInterface{ Loggerlog=Logger.getLogger(EmpDao.class); public

booleandel(Stringid){ //TODO

自动生成方法存根 System.out.println("正在删除数据!"); log.log(Level.INFO,"正在删除数据!");//使用日志 return

false; }

……}ProxyFactoryBean创建AOP代理(xml配置)<beanid="empdao"class="com.bean.EmpDao"/><!--设定代理类--><beanid="mypoxy"class="org.springframework.aop.framework.ProxyFactoryBean"> <propertyname="proxyInterfaces"> <value>com.bean.DaoInterface</value> </property> <!--程序中的切入点--> <propertyname="target"> <refbean="empdao"/>

</property></bean>指向接口的实现类指定特定的接口ProxyFactoryBean创建AOP代理(使用类)public

classUseProxyFactorBean{public

static

voidmain(String[]args){ String path=UseProxyFactorBean.class.getClass().getResource("/").getPath(); ApplicationContextctx=new FileSystemXmlApplicationContext(path+"/applicationContext.xml"); DaoInterface factorybean=(DaoInterface)ctx.getBean("mypoxy"); factorybean.save("aaa"); }}直接返回接口类型spring中AOP的三种代理方式第一种就是前面介绍的proxyFactoryBean的代理,这里就不再赘述。第二种就是CGLIB(CodeGeneratorLibrary--代码生成类库)代理。使用它的好处在于不用像java的动态代理那样去实现特定的接口,一个普通的java类就可以了。Spring中的自动代理,就是减少重复性的工作。spring中AOP的三种代理方式--CGLIB修改上例的配置文件信息(sping.xml)

<beanid="mypoxy"class="org.springframework.aop.framework.ProxyFactoryBean"> <!—设定CGLIB代理

<propertyname="proxyTargetClass"> <value>true</value> </property> <!--程序中的切入点--> <propertyname="target"> <refbean="empdao"/>

</property></bean>

好处在于不在指定特定的接口了!不在指定特定接口使用CGLIB代理完成方法调用的前通知Advice通知请求中断请求的通知在于我们的业务类在调用以前就开始自动执行的一种方式。Spring提供了以下几种执行方式1.Interceptionaroundadvice

Spring中最基本的Advice类型,提供了针对PointCut的预处理、后处理过程支持。我们将使用Interceptionaroundadvice完成这里的实例。2.Beforeadvice

仅面向了PointCut的预处理。3.Throwsadvice

仅面向PointCut的后处理过程中的异常处理。使用CGLIB代理完成方法调用的前通知4.AfterReturningadvice

仅面向PointCut返回后的后处理过程。5.Introductionadvice

Spring中较为特殊的一种Advice,仅面向Class层面(而不像上述Advice面向方法层面)。通过Introductionadvice我们可以实现多线程访问中的类锁定。编写自己的业务接口及实现类业务接口

packagecom.test;

publicinterfaceITest{ publicStringexecute(Stringstr); }实现类

packagecom.test;publicclassMyTestimplementsITest{publicStringexecute(Stringstr){//TODOAuto-generatedmethodstubSystem.out.println("主业务方法正在执行.....");return"主业务方法返回的结果---->"+str;}}中断处理类的编写Spring中采用了AOP联盟(AOPAlliance)12的通用AOP接口(接口定义位于aopalliance.jar)。这里我们采用aopalliance.jar中定义的MethodInterceptor作为我们的Advice实现接口

类代码如下:packagecom.bean;importjava.io.Serializable;ercept.*;publicclassMyMothedInterceptimplementsMethodInterceptor,Serializable{publicObjectinvoke(MethodInvocationarg0)throwsThrowable{System.out.println("===================================");System.out.println("中断请求开始执行......");System.out.println("5秒以后处理业务逻辑......");try{Thread.sleep(5000);}catch(RuntimeExceptione){e.printStackTrace();}System.out.println("========中断处理调用======");Objectobj=ceed();System.out.println("中断处理逻辑处理完成......");System.out.println("处理相关的日志信息......");System.out.println("打印相关的消息......");System.out.println(“====中断请求执行完成=======");returnobj;}}在spring.xml文件中的配置Spring.xml文件中的配置信息如下:<!--加入自己的中断请求类--><beanid="mypointrequest"class="com.bean.MyMothedIntercept"/><!--注入自己的业务类--><beanid="testbean"class="com.test.MyTest"/><!--注入spring容器的请求代理对象--><beanid="mybeanproxy"class="org.springframework.aop.framework.ProxyFactoryBean"><!--注入业务接口--><propertyname="proxyInterfaces"><value>com.test.ITest</value></property><!--指定代理的目标实现--><propertyname="target"><reflocal="testbean"/></property><!--制定中断请求的名称--><propertyname="interceptorNames"><value>mypointrequest</value></property></bean>客户端测试代码客户端测试代码ApplicationContextctx=new FileSystemXmlApplicationContext("D:\\prjspringao p\\WebRoot\\WEB-INF\\spring.xml");ITestts=(ITest)ctx.getBean("mybeanproxy");System.out.println(ts.execute("sss"));

输出的结果如下:

===================================中断请求开始执行......5秒以后处理业务逻辑......========中断处理调用======主业务方法正在执行.....中断处理逻辑处理完成......处理相关的日志信息......打印相关的消息......中断请求执行完成......===============================主业务方法返回的结果---->sssspring中AOP的三种代理方式—自动代理<beanid="empdao"class="com.bean.EmpDao"/><!--设定自动代理类--><beanid="mypoxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><propertyname="beanNames"><list><value>*Dao</value></list></property></bean>代理所有以Dao结尾的类测试代码String path=UseProxyFactorBean.class.getClass().getReso urce("/").getPath();ApplicationContextctx=newFileSystemXmlApplicationContext(path+"/sping2.xml");DaoInterfacefactorybean=(DaoInterface)ctx.getBean("empdao");factorybean.del("ss");Spring中的事务管理器Spring从不同的事务管理API中抽象了一整套的事务机制.开发人员不必了解底层的事务API,就可以利用这些事务机制.有了这些事务机制,事务管理代码就能独立于特定的事务技术了.Spring的核心事务管理抽象是它为事务管理封装了一组独立于技术的方法.无论使用Spring的哪种事务管理策略(编程式或声明式),事务管理器都是必须的.Spring中的事务管理器的不同实现

:在应用程序中只需要处理一个数据源,而且通过JDBC存取

:在JavaEE应用服务器上用JTA(JavaTransactionAPI)进行事务管理:用Hibernate框架存取数据库……事务管理器以普通的Bean形式声明在SpringIOC容器中需求数据表中的数据Account表Book表Book_STOCK表用事务通知声明式地管理事务事务管理是一种横切关注点为了在Spring2.x中启用声明式事务管理,可以通过txSchema中定义的<tx:advice>元素声明事务通知,为此必须事先将这个Schema定义添加到<beans>根元素中去.声明了事务通知后,就需要将它与切入点关联起来.由于事务通知是在<aop:config>元素外部声明的,所以它无法直接与切入点产生关联.所以必须在<aop:config>元素中声明一个增强器通知与切入点关联起来.由于SpringAOP是基于代理的方法,所以只能增强公共方法.因此,只有公有方法才能通过SpringAOP进行事务管理.在spring2.5配置文件中引入用于声明事务的tx命名空<beansxmlns=""xmlns:xsi=""xmlns:aop=""xmlns:context=""xmlns:tx=""xsi:schemaLocation="/spring-beans-2.5.xsd/spring-tx-2.5.xsd/spring-aop-2.5.xsd/spring-context-2.5.xsd"></beans>用事务通知声明式地管理事务示例代码声明事务管理器声明事务通知声明事务通知需要通知方法(即需要进行事务管理的方法)用@Transactional注解声明式地管理事务除了在带有切入点,通知和增强器的Bean配置文件中声明事务外,Spring还允许简单地用@Transactional注解来标注事务方法.为了将方法定义为支持事务处理的,可以为方法添加@Transactional注解.根据SpringAOP基于代理机制,只能标注公有方法.可以在方法或者类级别上添加@Transactional注解.当把这个注解应用到类上时,这个类中的所有公共方法都会被定义成支持事务处理的.在Bean配置文件中只需要启用<tx:annotation-driven>

元素,并为之指定事务管理器就可以了.如果事务处理器的名称是transactionManager,就可以在<tx:annotation-driven>元素中省略transaction-manager属性.这个元素会自动检测该名称的事务处理器.用@Transactional注解声明式地管理事务配置文件示例代码事务传播属性当事务方法被另一个方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.事务的传播行为可以由传播属性指定.Spring定义了7种传播行为.Spring支持的事务传播行为需求新定义Cashier接口:表示客户的结账操作修改数据表信息如下,目的是用户Tom在结账时,余额只能支付第一本书,不够支付第二本书:REQUIRED传播行为当bookService的purchase()方法被另一个事务方法checkout()调用时,它默认会在现有的事务内运行.这个默认的传播行为就是REQUIRED.因此在checkout()方法的开始和终止边界内只有一个事务.这个事务只在checkout()方法结束的时候被提交,结果用户一本书都买不了事务传播属性可以在@Transactional注解的propagation属性中定义Tx1开始Tx1结束checkout()purchase()purchase()配置数据源(mysql)<beanid="dataSource"class="mons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"value="org.gjt.mm.mysql.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8"/><propertyname="username"value="root"/><propertyname="password"value="123456"/><!--连接池启动时的初始值--> <propertyname="initialSize"value="1"/> <!--连接池的最大值--> <propertyname="maxActive"value="500"/> <!--最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止--> <propertyname="maxIdle"value="2"/> <!--最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请--> <propertyname="minIdle"value="1"/></bean>使用<context:property-placeholderlocation=“perties”/>属性占位符使用属性占位符方式配置数据源<context:property-placeholderlocation=“perties”/><beanid="dataSource"class="mons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"value="${driverClassName}"/><propertyname="url"value="${url}"/><propertyname="username"value="${username}"/><propertyname="password"value="${password}"/><!--连接池启动时的初始值--> <propertyname="initialSize"value="${initialSize}"/> <!--连接池的最大值--> <propertyname="maxActive"value="${maxActive}"/> <!--最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止--> <propertyname="maxIdle"value="${maxIdle}"/> <!--最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请--> <propertyname="minIdle"value="${minIdle}"/></bean>采用注解方式配置事务采用注解方式<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="dataSource"/>

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论