Spring入门笔记(二)

AOP: 全称是 Aspect Oriented Programming 即: 面向切面编程。
单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的
基础上,对我们的已有方法进行增强。
动态代理的特点
字节码随用随创建,随用随加载。
它与静态代理的区别也在于此。因为静态代理是字节码一上来就创建好,并完成加载。
装饰者模式就是静态代理的一种体现


动态代理常用的有两种方式
基于接口的动态代理
提供者: JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。
基于子类的动态代理
提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
要求:被代理类不能用 final 修饰的类(最终类)。
基于接口的动态代理对象创建方式代码示例

Proxy.newProxyInstance(三个参数)
* 参数含义:
* ClassLoader:和被代理对象使用相同的类加载器。
* Interfaces:和被代理对象具有相同的行为。实现相同的接口。
* InvocationHandler:如何代理

IActor proxyActor = (IActor) Proxy.newProxyInstance(
actor.getClass().getClassLoader(),
actor.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 执行被代理对象的任何方法,都会经过该方法。
* 此方法有拦截的功能。
*
* 参数:
* proxy:代理对象的引用。不一定每次都用得到
* method:当前执行的方法对象
* args:执行方法所需的参数
* 返回值:
* 当前执行方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

//写自己的增强代码

}


基于子类的动态代理创建方式

方法的参数:
* Class:被代理对象的字节码
* Callback:如何代理
Actor cglibActor = (Actor) Enhancer.create(actor.getClass(),new MethodInterceptor() {

* 参数:
* 前三个和基于接口的动态代理是一样的。
* MethodProxy:当前执行方法的代理对象。
* 返回值:
* 当前执行方法的返回值
 

               @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

                     //写自己的增强代码

              }
 

}
AOP 相关术语
Joinpoint(连接点):
所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的.

简单理解就是被代理对象的所有方法
Pointcut(切入点):
所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。简单理解就是被增强的方法
advice(通知/增强):
所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。增强的代码块,代码逻辑
通知的类型: 前置通知,后置通知,异常通知,最终通知,环绕通知。

Target(目标对象):
代理的目标对象。
Weaving(织入):
是指把增强应用到目标对象来创建新的代理对象的过程。
spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
Proxy(代理) :
一个类被 AOP 织入增强后,就产生一个结果代理类。
Aspect(切面):
是切入点和通知(引介)的结合。对那个方法进行怎么样增强

基于 XML 的 AOP 配置
第一步:把通知类用 bean 标签配置起来,将切面类交给spring容器管理

第二步:使用 aop:config 声明 开始aop 配置

<aop:config>

<!-- 配置的代码都写在此处 -->
 

</aop:config>

第三步:使用 aop:aspect 配置切面

属性:
id: 给切面提供一个唯一标识。
ref: 引用配置好的通知类 bean 的 id

<aop:aspect id=""  ref="" >
                <aop:before/>
                <aop:after-returning/>
                <aop:after-throwing/>
                <aop:after/>
                <aop:around/>
                * method        : 切面方法的名称
                * ponitcut-ref    :切入点的唯一表示
     </aop:aspect>

第四步:使用 aop:pointcut 配置切入点表达式

作用:
用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。
属性:
expression:用于定义切入点表达式。

表达式语法: execution([修饰符] 返回值类型 包名.类名.方法名(参数))
访问修饰符可以省略,返回值可以使用*号,表示任意返回值,包名可以使用*号,表示任意包,但是有几级包,需要写几个*

使用..来表示当前包,及其子包,类名可以使用*号,表示任意类,方法名可以使用*号,表示任意方法,参数列表可以使用..表示有无参数均可,有参数可以是任意类型
id: 用于给切入点表达式提供一个唯一标识

<aop:pointcut expression="execution(* cn.ithehe..*.*(..))" id="pt"/>

简单示例

<aop:config>
         <aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))"     id="pt1"/>
         <aop:aspect id="txAdvice" ref="txManager">
                      <!-- 配置环绕通知 -->
                 <aop:around method="transactionAround" pointcut-ref="pt1"/>
          </aop:aspect>
</aop:config>
基于注解的 AOP 配置
在配置文件中指定 spring 要扫描的包
    <context:component-scan base-package="com.itheima"></context:component-scan> 
    在 spring 配置文件中开启 spring 对注解 AOP 的支持 @EnableAspectJAutoProxy :开启对注解AOP的支持

    <aop:aspectj-autoproxy/>
    在通知类上使用@Aspect 注解声明为切面 
    在增强的方法上使用注解配置通知
    @Pointcut("execution(* com.ithehe.service.impl.*.*(..))")//切入点表达式的引用
    public void pt(){}
    
    @Before
    @after
    @afterReturning
    @around
    @afterThrowing
    可以结合@pointcut

猜你喜欢

转载自blog.csdn.net/minecodelife/article/details/81111662