Sprin-AOP动态代理

AOP动态代理

相关术语

  1. 连接点 Joinpoint
    • 可以被拦截的方法,即可以被增强的方法,这些方法就成为连接点
  2. 切入点Pointcut
    • 真正被拦截增强的方法
  3. 通知Advice
    • 增加的内容和功能,通常是封装的方法
  4. 引介Introduction
    • 类层面的增强,给原有类增加一些新的属性和方法
  5. 被增强的对象Target
    • 被增强的对象
  6. 织入Weaving
    • 将通知应用到目标对象的过程
  7. 代理对象Proxy
    • 代理对象
  8. 切入Aspect
    • 多个通知和多个切入点的集合

使用AOP的步骤

  1. 引用相关Spring相关jar包 -在创建spring工程的时候就自动引进了

  2. 引入AOP开发的相关jar包 -在创建Spring工程的时候就自动引进了

  3. 配置文件中引入AOP约束 -在创建Spring工程的时候就自动引进了

  4. 编写一个切面类

    • Myaspect.java
    package com.ly.test4;
    
    public class Myaspect {
        public void check() {
            System.out.println("切面类切入");
        }
    }
    
  5. 将切面交给Spring

    <!-- 将切面交给Spring管理 -->
        <bean id="myaspect" class="com.ly.test4.Myaspect"></bean>
    
  6. 配置AOP完成对目标的产生代理

    <!-- 配置AOP完成对目标的产生和代理 -->
        <aop:config>
            <!-- 配置切点 即是哪个方法需要增强 -->
            <aop:pointcut id="savepoint" expression=
                          "execution(* com.ly.test.dao.UserDaoImpl.delete(..))"></aop:pointcut>
            <!-- 切面配置 即增强的功能是什么 -->
            <aop:aspect ref="myaspect"> 
                <!-- 前置通知-->
                <aop:before method="check" pointcut-ref="savepoint"></aop:before>
            </aop:aspect>
        </aop:config>
    
    • 解析"execution(* com.ly.test.dao.UserDaoImpl.delete(..))"
      • *代表任意类型返回值
      • ..代表任意参数

AOP通知类型

  1. 前置通知

    <aop:before method="check" pointcut-ref="savepoint"></aop:before>
    
  2. 后置通知 -可以接受返回值

    • applicationContext.xml配置
    <!-- 没有接受返回值 -->
    <aop:after-returning method="check" pointcut-ref="savepoint" ></aop:after-returning>
    <!-- 接受返回值 returning参数必须和通知接受的参数名一致 -->
     <aop:after-returning method="check" pointcut-ref="savepoint" returning="res"></aop:after-returning>
    
    • Myaspect.java切面类需要接受参数的话

      public class Myaspect {
          public void check(String res) {
              System.out.println("res" + res)
          }
      }
      
  3. 环绕通知

    • 需要把切入点拿到切面类中处理,然后再返回,所以切面类必须有返回值Object类和参数接受切入点

      • Myaspect.java

        public class Myaspect {
        
        	public Object sorund(MethodInvocationProceedingJoinPoint joinPoint) throws Throwable {
                System.out.println("前置通知");
                //运行传入的方法,如果不运行,则原来的方法不执行
                Object proceed = joinPoint.proceed();
                System.out.println("后置通知");
                return proceed;
            }
        }
        
  4. 异常抛出通知

  5. 最终通知 -无论代码是否有异常,都会执行

  6. Spring单元测试 (不是过程,是教学用的)

  7. 测试 (不是过程,是教学用的)

Spring单元测试

  • applicationContext.xml

    <bean id="goodsDao" class="com.ly.test2.GoodsDaoImpl"></bean>
    
  • 读取applicationContext.xml 利用注解解决

    package com.ly.test4;
    
    import com.ly.test2.GoodsDao;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class AopTest {
    
        @Autowired
        @Qualifier("goodsDao")
        private GoodsDao goodsDao;
    
        @Test
        public void test1() {
            goodsDao.save();
        }
    }
    

    AOP开发的注解方式

    • 开启注解 -示例是前置通知

    • applicationContext.xml

      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      
    • Aspect.java切面类

      package com.ly.demo1;
      
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      import org.springframework.stereotype.Component;
      
      @Aspect
      public class Myaspect {
      
          @Before(value = "execution(* com.ly.demo1.Student.*(..))")
          public void check(){
              System.out.println("岂可岂可岂可no");
          }
      }
      
    • Student.java 被增强的对象

      package com.ly.demo1;
      
      import org.springframework.stereotype.Component;
      
      public class Student {
          public void save() {
              System.out.println("保存——");
          }
      }
      
    • DemoTest.java

      package com.ly.demo1;
      
      import org.springframework.stereotype.Component;
      
      public class Student {
          public void save() {
              System.out.println("保存——");
          }
      }
      

      其他注解通知

      package com.ly.demo1;
      
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.annotation.Around;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      import org.springframework.stereotype.Component;
      
      @Component("myaspect")
      @Aspect
      public class Myaspect {
      
          /**
           * 前置通知
           */
          @Before(value = "execution(* com.ly.demo1.Student.*(..))")
          public void check(){
              System.out.println("岂可岂可岂可no");
          }
      
          /**
           * 环绕通知
           */
          @Around(value = "execution(* com.ly.demo1.Student.*(..))")
          public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
              System.out.println("放在前面");
              Object proceed = joinPoint.proceed();
              System.out.println("放在后面");
              return proceed;
          }
      }
      

      注解扩展

      1. 给多个方法同时设置一个通知
      • 切面注入多个方法中使用和符号||

        package com.ly.demo1;
        
        import org.aspectj.lang.ProceedingJoinPoint;
        import org.aspectj.lang.annotation.Around;
        import org.aspectj.lang.annotation.Aspect;
        import org.aspectj.lang.annotation.Before;
        import org.springframework.stereotype.Component;
        
        @Component("myaspect")
        @Aspect
        public class Myaspect {
        
            /**
             * 前置通知 应用在多个方法之上
             */
            @Before(value = "execution(* com.ly.demo1.Student.save(..)) || execution(* com.ly.demo1.Student.delete(..))")
            public void check(){
                System.out.println("岂可岂可岂可no");
            }
        
        
      1. 设置通知名

        //设置一个通知名
        @Pointcut(value = "execution(* com.ly.demo1.Student.save())")
        private void saveAspect() {}
        
        //直接使用通知名就行了
         @Around("Myaspect.saveAspect()")
            public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
                System.out.println("放在前面");
                Object proceed = joinPoint.proceed();
                System.out.println("放在后面");
                return proceed;
            }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值