Spring aop
aop:(Aspect Oriented Programming)面向切面编程,纵向重复,横向抽取
代理: 生活中的实例:找明星拍戏,上综艺。拍戏 直接找明星,说明明星太小。如果明星有点名气,那就不能直接访问了,必须先通过先访问明星的经纪人,然后由经纪人访问明星,经纪人就是明星的代理。放在程序当中,有一个目标对象,一个代理对象, 你想访问目标对象,必须访问代理对象,由代理对象决定访问目标对象。Java 中提供了一个类Proxy 能够实现代理
Spring AOP
利用了代理技术 主要应用于在service层的事务管理
Spring实现aop 有两种方法
(1)动态代理(建议):被代理对象必须实现接口,如果没有接口则不能实现动态代理
(2)cglib代理: 第三方的代理技术。任何类都可以实现代理,使用继承的机制实现代理,所以被代理对象不能被final修饰
手动实现 动态代理
准备一个UserService UserServiceImpl
准备获得UserService代理对象的类
1. 获取代理对象 通过调用Proxy 的new ProxyInstance方法 创第三个参数(1本类的加载器,2代理对象的接口(实现类获得接口),3this),这样就得到了一个代理对象
2. 实现代理对象的方法 让这个类 实现InvocationHandler接口 实现了它的方法 invoke(代理的对象,调用的方法,方法的的参数)
被代理的对象方法还是要被调用,所有调用method,invoke()两个参数,一个是被代理的对象,参数 给该类加上一个属性被代理对象,并给该类添加构造函数,在调用被代理对象方法的前后 可以加上对应的内容
public class UserServiceProxyFactory implements InvocationHandler{ |
cglib代理
public class UserServiceProxyFactory2 implements MethodInterceptor{
|
Spring AOP 配置
7个专业名词
JoinPoint (连接点)
1. 导包
4+2 + 2+2 spring(aop aspect) spring依赖包()
2. 准备目标对象 UserServiceImpl
3. 准备通知
4. 配置applicationContext.xml文件
导入约束:
直接打入<aop:conf 如果有提示 直接打回车 自动帮你导入约束
没有的话 就手动导入
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop <!--配置aop切入-->
|
配置切入:
1. 配置切入点
<aop:pointcut id=”” expreession=”” 目标对象要增强的方法</aop:pointcut> |
2. 配置切面: 将通知织入到对应的切入点
<aop:aspect ref="通知"> |
多种方式切入
总共有五种切入方式
1. 在目标对象方法前调用
<aop:before method="before" pointcut-ref="pc"></aop:before> |
2. 在目标对象方法后调用(没有异常,有异常不调用)
<aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning> |
3. 在目标对象方法后(不管啊有无异常)
<aop:after method="after" pointcut-ref="pc"></aop:after> |
4. 在目标对象方法前后调用代码(特殊,在通知中的方法)
ProceedingJoinPoint(参数)如果有异常方法后不调用
<aop:around method="around" pointcut-ref="pc"></aop:around> |
5. 只在目标对象方法出现异常时调用
<aop:after-throwing method="throwException" pointcut-ref="pc"></aop:after-throwing> |
<!--引入切入点 写那个类中的方法代码块--> |
实现代码:
<aop:config> proxy-target-class="true" 基于类的代理将起作用 --> |
使用注解的方式配置AOP(了解)
1. 开启注解模式
<!--开启注解模式--> |
2. 注解切面
再通知上面加上一个注解 @ Aspect
再通知的方法上面加上切点
五种:
@Before(表达式) @After @AfterReturning @Around @AfterThrowing
@Before("execution(* cn.hd.springProxyAnnotation.impl.UserServiceImpl.*(..))") |
书写表达方式有两种
1. 直接写
@Before("execution(* cn.hd.springProxyAnnotation.impl.UserServiceImpl.*(..))") |
2. 配置一个切点 调用类的方法获得切点
public class MyAdvice { } @AfterReturning("MyAdvice.pc()") |