spring-03

前言

练习SpringAOP面向切面编程

代理模式

代码spring03-1

1.代理模式的概念

1.代理需要实现和被代理者相同的接口。只有实现了相同的接口。代理者才能和被代理者看起来一模一样。

2.代理者在完成目标方法之外还要完成其他的工作。

代码spring03-2

2.传统模式中把事务写在service层中非常不合适

这样使得service变得不单纯。
理想模式:业务层的代码只处理业务。事务代码有专门的人负责。不应该写在一起。实现代码的解耦。

代码spring03-3

3.静态代理模式

静态代理模式需要实现与被代理者相同的接口。为了看起来和目标对象一致需要修改ID

静态代理模式中包含了

1、目标对象

2、在目标对象完成操作之外完成额外的工作

好处:

实现了代码的分离。让业务层代码只处理业务。事务代码只处理事务,两者松耦合。

缺点:

事务添加的代码重复,复用性不好。基本不用。

代理模式:


4.动态代理


 一、JDK的动态代理

优点:

1.能够解决重复代码的编写,并且继承了静态代理的所有的优点。

缺点:

1.所有的方法都添加上了事务。这样做不合理。虽然可以在invoke方法中可以根据方法判断是否要加上事务但是这样代码的可读性就变差了。

2.动态代理的局限性高,不能做到灵活的运用。比如添加事务需要一个动态代理,添加日志需要写一个动态代理,添加权限需要写一个动态代理。

3.target.getClass().getInterfaces()要求被代理者必须实现接口。这样才能创建出代理对象

二、Cglib动态代理模式

代码spring03-5

特点:将来生成的代理对象都是目标对象的子类

     无论目标对象是否有接口,都能生成代理对象。

代码实现:
public static Object getProxy(final Object target,final TransactionManager tx){
 
//cgLib动态代理的实现
 
//增强器
Enhancer enhancer = new Enhancer();
 
//设置参数
enhancer.setInterfaces(target.getClass().getInterfaces());
 
//设置目标对象为父类
enhancer.setSuperclass(target.getClass());
 
//设置回调
enhancer.setCallback(new MethodInterceptor() {
 
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
try {
tx.begin();
method.invoke(target, args);
tx.commit();
} catch (Exception e) {
tx.rollBack();
}
return null;
}
});
 
//真正生成代理对象
return enhancer.create();
 
}

三:spring底层用CGlib和JDK的动态代理帮我们生成代理对象,这种方式更加的灵活

AOP的学习:

1.切面(Aspect:一个关注点的模块化,这个关注点可能会横切多个对象。做额外的操作。

2.连接点(Joinpoint:在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。目标对象的执行方法。

3.通知(Advice:在切面的某个特定的连接点上执行的动作。

4.切入点(Pointcut:匹配连接点的断言。匹配规则只有规则匹配了才能执行通知。

5.目标对象(Target Object: 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。就是方法真正执行的对象

6.AOP代理(AOP Proxy:AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

7.织入(Weaving:把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。织入就是形成切面的过程(通知+目标对象整合)

AOP的实现步骤

1.导入jar包(5jar



2.导入头文件

<?xmlversion="1.0" encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.2.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

 红色是相比以前增加的

  蓝色是复制后更改的地方(要改5个地方)

3. 编写切面和通知

(1).编写切面

//自定义的切面

@Component("txAspect")

public classTransactionAspect {

 

@Resource

privateTransactionManager tx;

 

(2).编写通知

public voidaround(ProceedingJoinPoint joinPoint) throws Throwable{

try {

tx.begin();                        //事务开始

joinPoint.proceed();   //目标对象执行

tx.commit();

} catch(Exception e) {

tx.rollBack();

}

}

}

 

 

(3).xml配置切面

<aop:config>

<!--切入点  -->

<aop:pointcutexpression="within(service.*)"id="pc"/>                

<aop:aspectref="txAspect">

<aop:aroundmethod="around" pointcut-ref="pc"/>

</aop:aspect>

</aop:config>

(4)调用关系



通知的类型

代码spring03-7

1.aop:before     前置通知   在目标方法执行之前要执行的。日志

2.aop:around    环绕通知   在目标方法执行之前和执行之后都需要执行的通知

3.aop:after-returning   后置通知在目标方法执行之后再执行的通知。

4.aop:after-throwing    异常通知当执行目标方法之后抛出异常才执行异常通知。

5.aop:aftermethod      最终通知 finally最后肯定会被执行的通知。

环绕通知中必须手动的放行目标方法(否则程序会中断)而其他的通知目标方法都会自动执行,和通知没关系(没赋予除环绕通知之外的其他通知管理目标方法的权利)

注意事项

<aop:after-throwingmethod="afterThrow" pointcut-ref="pc1"throwing="thro"/>

throwing="thro"参数要和接收参数匹配否则会报如下错

注意

ProceedingJoinPoint   只能用于环绕通知。

JoinPointjoinPoint  其他通知使用的参数

这些参数必须位于参数列表的第一位否则会报错。


两个方法:

System.out.println(joinPoint.getSignature().getName());

System.out.println(joinPoint.getTarget().getClass());

结果如下图:

后置通知的返回值问题

1后置通知如果与环绕通知一起执行,后置通知想拿到返回值结果。则环绕通知中必须加return

2如果切面中没有环绕通知,则后置通知可以获得返回值

如果后置通知 返回值参数 不匹配(不一致)会报错






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值