【Spring四】AOP之XML配置

前端之家收集整理的这篇文章主要介绍了【Spring四】AOP之XML配置前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
AOP:Aspect Oriented Programming 面向切面编程

面向切面编程的核心是动态代理设计模式。请先参见动态代理设计模式笔记。

以Hibernate保存一个对象到数据库为例,由于保存数据时需要开启事务,利用面向切面编程思想,将事务的处理分离出来,当作一个切面来处理。

jdk的动态代理的缺点:
1、在拦截器中,切入点的判断是非常复杂的
2、虽然实现了切面与目标类的松耦合,但是在拦截器中还得实现结合过程

一.springAOP的原理
目标类:在目标类的方法调用的前后,我们需要加入自己的逻辑;
切面:包含了所有的封装了自己的逻辑方法的类
切入点:目标类里的需要加入额外逻辑的方法
通知:切面里的自己的封装自己的逻辑的方法
比如Hibernate中,目标类是XDaoImpl,切入点是XDao.save(xx)方法通知是开启事务,以及commit,切面就是封装了开启事务和commit的类;即在save方法执行前,需要开始事务,执行后,需要提交事务!

1、当启动spring容器的时候,
<bean id="classDao" class="cn.itheima03.spring.aop.xml.ClassesDaoImpl"></bean>
<bean id="myTransaction" class="cn.itheima03.spring.aop.xml.MyTransaction"></bean>

把这两个bean创建对象了
2、解析<aop:config>便签
(1)、解析切入点表达式<aop:pointcut>,切入点针对的是函数,从函数进行切入,把表达式解除出来以后和 spring中的bean进行匹配
(2)、如果匹配成功,则为该bean创建代理对象,在创建代理对象的过程中,把目标方法通知结合在一起了
如果匹配不成功,则直接报错
(3)、当客户端调用context.getBean时,获取到的
(1)、如果该对象有代理对象,则返回代理对象
(2)、如果该对象没有代理对象,则返回对象本身
3、<aop:aspect>切面标签:
在切面中配置各种通知,这些通知就我们自己需要额外执行的逻辑,有的逻辑在切入点函数执行前执行,用<aop:before>配置;有的需要在切入点方法执行之后执行,使用<aop:after>配置;还有的是执行切入点函数出现异常后执行,等的。。
说明:
spring容器内部会自动判断:
如果目标类实现了接口,则采用jdkproxy
如果目标类没有实现接口,则采用cglibproxy

二.关于通知通知就是切面里的方法,又称Advive,是在方法执行前和后需要执行的自己的代码
前置通知
1、在目标方法之前执行
2、无论目标方法遇到异常都执行
后置通知
1、在目标方法后执行
2、如果目标方法遇到异常,则不执行
3、可以获取连接点的一些信息
最终通知
1、相当于finally
2、无论目标方法是否遇到异常,都执行

异常通知
1、获取目标方法抛出的异常信息
2、throwing参数的配置才能获取信息

环绕通知
相当于jdkproxy的invoke方法

三.下面使用Spring的AOP来处理Hibernate保存对象。

1.配置文件:applicationContext.xml
< beans xmlns="http://www.springframework.org/schema/beans"@H_403_201@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"@H_403_201@xmlns:aop="http://www.springframework.org/schema/aop"@H_403_201@
xsi:schemaLocation="@H_403_201@
http://www.springframework.org/schema/beans@H_403_201@
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd@H_403_201@
http://www.springframework.org/schema/aop@H_403_201@
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"@H_403_201@ >
<!-- 1、目标类 2、切面 3、进行AOP的配置 -->
< bean id="classDao"@H_403_201@class="cn.itheima03.spring.aop.xml.ClassesDaoImpl"@H_403_201@></bean>
< bean id="myTransaction"@H_403_201@class="cn.itheima03.spring.aop.xml.MyTransaction"@H_403_201@></bean>

< aop:config >
<!-- 切入点表达式 expression切入点表达式 id 唯一标示 -->
<aop:pointcut
expression="execution(* cn.itheima03.spring.aop.xml.ClassesDaoImpl.*(..))"@H_403_201@
id="perform"@H_403_201@/>

<!--ref引向切面 切面里包含各种各样的通知,这些通知都是我们自己想要额外实现的东西,比如开启事务等。。-->

<aop:aspectref="myTransaction"@H_403_201@>
<!-- 方法执行之前执行 -->
<aop:beforemethod="beginTransaction"@H_403_201@pointcut-ref="perform"@H_403_201@/>

<!-- 后置通知 returning 返回值 要与方法中的参数的名字相对应 -->
<aop:after-returningmethod="commit"@H_403_201@pointcut-ref="perform"@H_403_201@returning="val"@H_403_201@/>

<!-- 最终通知 无论目标方法是否有异常,都执行 -->
<aop:aftermethod="finnalyMethod"@H_403_201@pointcut-ref="perform"@H_403_201@/>

<!-- 异常通知 throwing 获取目标方法抛出的异常信息 -->
<aop:after-throwingmethod="throwingMethod"@H_403_201@pointcut-ref="perform"@H_403_201@throwing="ex"@H_403_201@/>

<!-- 相当于 代理中invoke 方法,可以控制切入点的执行 -->
<aop:aroundmethod="aroundMethod"@H_403_201@pointcut-ref="perform"@H_403_201@/>

</aop:aspect>
</ aop:config >
</ beans >

关于切入点表达式:切入点表达式匹配的是方法,一个方法的完整声明为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)

问号代表可有可无,没有问号代表一定要有!
下面是一个方法完整声明的示例:
切入点表达式示例:
  • execution(public * *(..)) 所有的公共方法
  • execution(* set*(..)) 以set开头的任意方法
  • execution(* com.xyz.service.AccountService.*(..))com.xyz.service.AccountService类里的所有的方法
  • execution(* com.xyz.service.*.*(..)) com.xyz.service包下的所有类的所有的方法
  • execution(* com.xyz.service..*.*(..)) com.xyz.service包及子包中所有的类的所有的方法
  • execution(* cn.itheima03.spring..*.*(String,*,Integer))
  • execution(* cn.itheima03.*.*.spring.*..*.*(..)) 参数..代表任意类型的任意参数,参数可以是0个
如cn.itheima03.a.b.spring.c.d.A.a()能匹配最后一个表达式!


2.java代码

@H_502_1272@public interfaceClassesDao {
@H_502_1272@public voidsaveClasses(Classes classes);
@H_502_1272@public voidupdateClasses(Classes classes);
@H_502_1272@public List<Classes> getClasses();
}
===========================================
@H_502_1272@public classClassesDaoImplextendsHibernateUtils{

@H_502_1272@public String saveClasses(Classes classes) {
inta= 1/0;
sessionFactory@H_403_201@.getCurrentSession().save(classes);
return"aaaa";
}

@H_502_1272@public List<Classes> getClasses() {
returnsessionFactory@H_403_201@.getCurrentSession().createQuery("from Classes").list();
}

@H_502_1272@public voidupdateClasses(Classes classes) {
sessionFactory@H_403_201@.getCurrentSession().update(classes);
}

}
===========================================
@H_502_1272@public classHibernateUtils {
@H_502_1272@public staticSessionFactorysessionFactory@H_403_201@;
@H_502_1272@static {
Configuration configuration = newConfiguration();
configuration.configure();
sessionFactory@H_403_201@= configuration.buildSessionFactory();
}
}
===========================================
@H_502_1272@public classMyTransactionextendsHibernateUtils{
@H_502_1272@private Transactiontransaction;
/**
* 前置通知
* JoinPoint 能够调用该API得到连接点的一些信息
*/
@H_502_1272@public voidbeginTransaction(JoinPoint joinPoint){
System. out@H_403_201@.println(joinPoint.getSignature().getName());
this.transaction=sessionFactory@H_403_201@.getCurrentSession().beginTransaction();
}
/**
* 后置通知
* 1、获取目标方法的返回值
*/
@H_502_1272@public voidcommit(Object val){
System. out@H_403_201@.println(val);
this.transaction.commit();
}
/**
* 最终通知
*/
@H_502_1272@public voidfinnalyMethod(){
System. out@H_403_201@.println("finally method");
}
/**
* 异常通知
*/
@H_502_1272@public voidthrowingMethod(Throwable ex){
/**
* 输出目标方法的异常信息
*/
System. out@H_403_201@.println(ex.getMessage());
}
/**
* 环绕通知
* 1、如果不执行joinPoint.proceed();,目标方法是不执行的
* 2、在目标方法执行的上下文添加内容
*/
@H_502_1272@public voidaroundMethod(ProceedingJoinPoint joinPoint){
try{
System. out@H_403_201@.println("aaaa");
joinPoint.proceed(); //执行目标方法
System. out@H_403_201@.println("bbbb");
} catch(Throwable e) {
e.printStackTrace();
}
}
}
===========================================
/**
* 注意的点
* 1、代理对象的方法体的内容就是拦截器 中invoke方法体的内容
* 2、在客户端,用代理对象调用方法的时候进去了invoke方法
*/
@H_502_1272@public classClassesDaoTest {
@Test
@H_502_1272@public voidtestSaveClasses(){
ApplicationContext context = newClassPathXmlApplicationContext("cn/itheima03/spring/aop/xml/applicationContext.xml");
ClassesDaoImpl classesDao = (ClassesDaoImpl)context.getBean( "classDao" );
Classes classes = newClasses();
classes.setCname( "afds");
classesDao.saveClasses(classes);
}
}


四.多切面的例子

假如查看工资需要经过日志管理,安全管理,权限管理后才能查看工资。

目标类:查看工资的类
切面:日志管理,安全管理,权限管理
切入点:查看工资的方法
1.java代码
/**
* 切面
* 日志管理
*/
@H_502_1272@public classLogger {
@H_502_1272@public voidinterceptor() {
System. out@H_403_201@.println("logging");
}
}
===========================================
/**
* 安全管理
*/
@H_502_1272@public classSecurity {
@H_502_1272@public voidinterceptor() {
System. out@H_403_201@.println("security");
}
}
===========================================
/**
* 权限管理
*/
@H_502_1272@public classPrivilege{
@H_502_1272@private Stringaccess;

@H_502_1272@public String getAccess() {
returnaccess;
}

@H_502_1272@public voidsetAccess(String access) {
this.access= access;
}

@H_502_1272@public voidinterceptor(ProceedingJoinPoint joinPoint) {
if("admin".equals(this.access)){
try{
joinPoint.proceed();
} catch(Throwable e) {
e.printStackTrace();
}
} else{
System. out@H_403_201@.println("对不起,没有权限查看....");
}
}
}
===========================================
/**
* 目标类
*/
@H_502_1272@public classSalaryManagerImplimplementsSalaryManager{

@Override
@H_502_1272@public voidshowSalary() {
System. out@H_403_201@.println("正在查看工资");
}
}
===========================================
@H_502_1272@public classSalaryTest {
@Test
@H_502_1272@public voidtest(){
ApplicationContext context= newClassPathXmlApplicationContext("cn/itheima03/spring/aop/multiaspect/applicationContext.xml");
SalaryManager salarmManager=(SalaryManager) context.getBean( "salaryManager" );
salarmManager.showSalary();
}
}
===========================================

< beans xmlns="http://www.springframework.org/schema/beans"@H_403_201@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"@H_403_201@
xmlns:aop="http://www.springframework.org/schema/aop"@H_403_201@
xsi:schemaLocation="@H_403_201@
http://www.springframework.org/schema/beans@H_403_201@
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd@H_403_201@
http://www.springframework.org/schema/aop@H_403_201@
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"@H_403_201@ >

<!--目标类, 切面类,aop -->

< bean id="salaryManager"@H_403_201@class="cn.itheima03.spring.aop.multiaspect.SalaryManagerImpl"@H_403_201@></bean>
< bean id="logger"@H_403_201@class="cn.itheima03.spring.aop.multiaspect.Logger"@H_403_201@></bean>
< bean id="security"@H_403_201@class="cn.itheima03.spring.aop.multiaspect.Security"@H_403_201@></bean>
< bean id="privilege"@H_403_201@class="cn.itheima03.spring.aop.multiaspect.Privilege"@H_403_201@>
<propertyname="access"@H_403_201@value="admin"@H_403_201@></property>
</ bean >
< aop:config >
<!--切入点 -->
<aop:pointcutexpression="execution(* cn.itheima03.spring.aop.multiaspect.SalaryManagerImpl.*(..))"@H_403_201@id="sm"@H_403_201@/>
<!-- 切面 -->
<aop:aspectref="logger"@H_403_201@>
<aop:beforemethod="interceptor"@H_403_201@pointcut-ref="sm"@H_403_201@/>
</aop:aspect>
<aop:aspectref="security"@H_403_201@>
<aop:beforemethod="interceptor"@H_403_201@pointcut-ref="sm"@H_403_201@/>
</aop:aspect>
<aop:aspectref="privilege"@H_403_201@>
<!--环绕切入点 -->
<aop:aroundmethod="interceptor"@H_403_201@pointcut-ref="sm"@H_403_201@/>
</aop:aspect>
</ aop:config >
</ beans >
原文链接:https://www.f2er.com/xml/296440.html

猜你在找的XML相关文章