AOP的自动代理(基于AspectJ框架)
博客专区 > T-Brain 的博客 > 博客详情
AOP的自动代理(基于AspectJ框架)
T-Brain 发表于2年前
AOP的自动代理(基于AspectJ框架)
  • 发表于 2年前
  • 阅读 24
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】如何购买服务器最划算?>>>   

AOP的通知类型:

aop联盟 定义 aop通知类型,spring 对 aop联盟规范支持。

                        AOP 联盟不是Spring的,先是AOP联盟定义了一个接口org.springframework.aop.Advice 而Spring觉得不错,就改写了分成5种类型

aop联盟定义5种通知

前置通知 org.springframework.aop.MethodBeforeAdvice

在目标方法执行前实施增强

后置通知 org.springframework.aop.AfterReturningAdvice

在目标方法执行后实施增强

环绕通知 org.aopalliance.intercept.MethodInterceptor

在目标方法执行前后实施增强

异常抛出通知 org.springframework.aop.ThrowsAdvice

在方法抛出异常后实施增强

引介通知 org.springframework.aop.IntroductionInterceptor(了解)对一个类进行增强(添加方法或属性等)

在目标类中添加一些新的方法和属性

如果使用aop联盟规范进行aop开发,所有的通知必须实现接口。(底层为了确定通知方法名称)


Advisor和Aspect区别:

    Advisor : Spring传统的切面.一般都是由一个切入点和一个通知的组合.(单个)

    Aspect  : Aspect是真正意义上的切面.是由多个切入点和多个通知组合.(多个)



AOP基于AspectJ的自动代理(实现了接口,配置用<aop:Advisor>):

因为使用AOP,所以Spring需要的包以外,还要导入

                    联盟API开发包.jar----------->(依赖包下)

                    AOP所需要的核心包.jar----->(主包下)


1.切面类

    需要总结:

            需要根据AOP联盟确定一个通知类型:这里使用环绕通知

            所以切面类随便写,随便实现一个通知类型,重写里面的invok方法在,通过参数调用

                    proceed()执行目标类,前后可以写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.mickeymouse.proxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
  * 切面类:包含两个通知(增强)
     环绕通知必须手动执行方法
  * @author Mickey-Mouse
  *
  */
public class MyAspect implements MethodInterceptor {
     public Object invoke(MethodInvocation mi) throws Throwable {
         System.out.println( "已校验是否符合身份" );
         //环绕通知必须手动执行方法
         Object object = mi.proceed();
         System.out.println( "方法已经执行完--->后处理" );
         return object;
     }
}
2.目标类(已实现接口)
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.mickeymouse.proxy;
public class ProductsServiceImpl implements ProductsService {
     /**
      * 目标类:
      * 里面有两个连接点
      */
     public void addProducts(){
         System.out.println( "添加商品成功" );
     }
     public void updateProducts(){
         System.out.println( "修改商品成功" );
     }
}
3.自动代理XML配置

    因为是AOP开发,所有需要引入AOP的DTD约束

     与AOP的半自动代理区别在于:

       半自动代理没有使用AOP约束,要手动配置代理类与目标类的关系

       半自动代理是基于ProxyFactoryBean的代理类:

            缺点:

                    * 配置麻烦:

                    * 需要为每一个要增强的类配置一个ProxyFactoryBean.(只要有增强,就需要写一个ProxyFactoryBean的配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<? xml version = "1.0" encoding = "UTF-8" ?>
        xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop = "http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
<!-- bean definitions here -->
<!-- 自动代理模式 -->
<!-- 创建切面类 -->
< bean id = "myAspect" class = "com.mickeymouse.proxy.MyAspect" />
<!-- 创建目标类实现 -->
< bean id = "productsService" class = "com.mickeymouse.proxy.ProductsServiceImpl" />
<!-- 利用AOP约束,建立切面的 通知与切入点  之间的关系 -->
<!-- AOP的配置头 -->
< aop:config >
     <!--
      切入点配置:
      expression:AspectJ编程的表达式(说明利用了这个框架,所以注意导包)
      Id:切入点名称,连接通知的索引名
      -->
     < aop:pointcut expression = "execution(* com.mickeymouse.proxy.ProductsServiceImpl.*())" id = "mypointcut" />
     <!--
     切面配置:
       advice-ref:通知/增强点
       pointcut-ref=切点
       proxy-target-class="true" 表示强制使用CGLIB
      因为Spring默认是使用动态代理的方式,而CGLIB是使用目标类     生成子类代理的方式(也就是不使用接口)
     -->  
     < aop:advisor advice-ref = "myAspect" pointcut-ref = "mypointcut" />
</ aop:config >
</ beans >
XML分析:(总结4步)

1.配置切面类的Bean实例

2.配置目标类的Bean实例

3.配置切入点(结合exeution表达式)

4.配置切面(切入点和通知/加强点)


结果:




AOP自动代理:(切面类不需要实现接口/配置用<aop:aspect>)

1 . 目标类:(同上)
2 . 切面类:(随便写)eg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.mickeymouse.proxy.auto;
import org.aspectj.lang.ProceedingJoinPoint;
/**
  * 切面类:随便写
  * @author Mickey-Mouse
  *
  */
public class MyAspect {
     /**
      * 环绕配置切面类
      * @param proceedingJoinPoint 环绕需要手动开启方法
      * @return
      * @throws Throwable
      */
     public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
         System.out.println( "已校验是否符合身份" );
         Object object = proceedingJoinPoint.proceed();
         System.out.println( "方法已经执行完--->后处理" );
         return object;
     }
}
3 . XML配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 自动代理模式 -->
     <!-- 切面类 -->
     < bean id = "myAspect" class = "com.mickeymouse.proxy.auto.MyAspect" />
     <!-- 目标类 -->
     < bean id = "productsService" class = "com.mickeymouse.proxy.auto.ProductsServiceImpl" />
     <!-- AOP自动代理配置: -->
     < aop:config >
         <!-- 切入点 -->
         < aop:pointcut expression = "execution(* com.mickeymouse.proxy.auto.ProductsServiceImpl.*())" id = "mypointcut" />
         <!-- 切面 -->
         < aop:aspect ref = "myAspect" >
             < aop:around method = "around" pointcut-ref = "mypointcut" />
         </ aop:aspect >
     </ aop:config >
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.mickeymouse.proxy.auto;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
     @Test
     public void test1(){
         ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "applicationContext.xml" );
         ProductsService bean = applicationContext.getBean( "productsService" ,ProductsService. class );
         bean.addProducts();
         bean.updateProducts();
     }
}
结果图:




共有 人打赏支持
粉丝 1
博文 44
码字总数 46138
×
T-Brain
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: