大数据WEB阶段Spring框架 AOP面向切面编程(一)

Spring — AOP面向切面编程(一)

一、代理模式概述

  1. 代理的特点:(目标对象即被代理者)
    1. 实现和目标对象相同的接口
    2. 具备和目标对象的方法
    3. 代理者不仅要做目标对象的方法 , 还要做一些额外的操作
  2. 使用场景:
    1. 事务
    2. 权限控制
    3. 统计每个方法的执行时间

二、静态代理


1. 静态代理优点
1. 解耦
2. 静态代理缺点:
1. 一个代理类只能服务于一个被代理 , 如果被代理类很多 , 则操作会非常繁琐
2. 代码复用性不高 , 重复代码太多
3. 代理类的通用性几乎为0
4. 案例: 把service层的事务管理操作解耦

    事务管理类
    @Component
    public class TXManage {
        public void startTx(){
            System.out.println("开启事务");
        }
        public void commti(){
            System.out.println("提交事务");
        }
        public void rollback(){
            System.out.println("回滚事务");
        }
    }
    静态代理类
    注意
    实现与代理目标相同的接口
    需要指定id , 与注解的机制有关
    @Component("personService")
    public class StaticProxy implements PersonService{
        @Autowired
        private TXManage tx ;
        @Autowired
        private PersonServiceImpl pl;
        @Override
        public void savePerson(Person person) {
            try{

                tx.startTx();
                pl.savePerson(person);
                tx.commti();
            }catch(Exception e){
                tx.rollback();
            }

        }

    }

三、动态代理


1. 动态代理分为两种:
1. JDK提供的动态代理
2. CGLib动态代理
2. JDK提供的动态代理
1. 优点:
1. 继承静态代理的优点 , 一个代理类可以为多个目标类服务
2. 提高代码复用性
2. 缺点:
1. 并不是所有的方法都需要代理 , 需要进行方法过滤 , 过程繁琐
3. 必须要求目标类有接口
4. 案例: 把service层的事务管理操作解耦

        事务管理类   
        @Component
        public class TXManage {
            public void startTx(){
                System.out.println("开启事务");
            }
            public void commti(){
                System.out.println("提交事务");
            }
            public void rollback(){
                System.out.println("回滚事务");
            }
        }

        动态代理生成类
        @Component
        public class DynamicProxy {
            @Autowired
            private TXManage tx;
            public  Object getProxy(final Object tagert){
                Object proxy = Proxy.newProxyInstance(tagert.getClass().getClassLoader(), tagert.getClass().getInterfaces(), new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                            tx.startTx();
                            Object result = method.invoke(tagert, args);
                            tx.commti();
                        return result;
                    }
                });
                return  proxy;
            }
        }
        改造调用service的层 , 使他调用的是代理之后的service
        @Controller
        public class PersonServlet {
            @Autowired
            private PersonService personService;
            @Autowired
            private DynamicProxy dp;
            public void savePerson(Person  person){
                PersonService ps = (PersonService) dp.getProxy(personService);
                ps.savePerson(person);
            }
        }
  1. CGLib动态代理
    1. 优点:
      1. 继承JDK动态代理的优点
      2. 并不需要目标对象有接口
    2. 缺点:
      1. 方法过滤繁琐

四、Spring AOP面向切面编程

  1. Spring AOP 继承了以上代理所有的优点 , 并且可以对方法进行精准过滤
  2. Spring AOP 内部实现就是通过两种动态代理来实现的 , 进行了封装
  3. AOP:
    1. 是一种编程思想 , 可以实现把某些具体的功能的代码放在一个切面(类)当中 , 在不改动原来项目结构的同时 , 把切面插入到工程中 。 使用 这种编程思想 , 可以使项目的耦合程度降到最低
  4. Spring AOP 的相关概念:
    1. 切面(Aspect):
      1. 就是一个类 , 如: 事务的切面类 、 权限控制的切面类 、 日志输出切面类 。。。
    2. 连接点(Joinpoint):
      1. 代表目标类中的方法
    3. 通知(Advice):
      1. 切面中的方法 , 分为五种通知:
        1. 前置通知: 目标方法执行之前的通知
        2. 后置通知: 目标方法执行之后的通知
        3. 最终通知: 目标方法抛出异常之后的通知(相当于 finally块)
        4. 环绕通知: 目标方法执行前后执行的通知
        5. 异常通知: 目标方法发生异常执行的通知(相当于catch块)
    4. 切入点(Pointcut): 过滤方法的规则 , 只有满足切入点的规则才会执行切面中的通知
    5. 引入:
    6. 目标对象:
      1. 真正执行目标方法的类
    7. AOP代理对象:
      1. 在否和切入点的规则的吧前提下 , 真正执行的对象都是代理对象
    8. 织入:
      1. 代理对象的方法体 , 用来连接通知和目标对象
  5. AOP实现

    1. 实现步骤:
      1. 导入相关jar包
      2. 编写配置文件的头(导入Spring aop约束)
      3. 编写目标类
      4. 编写切面和通知
      5. 配置切入点表达式
      6. 配置切面和通知
    2. 导入相关jar包
      1. spring-aop.jar
      2. spring-aspects.jar
      3. aopectjrt.jar
      4. aspectjweaver.jar
      5. aopalliance.jar
    3. 编写配置文件的头

      <?xml version="1.0" encoding="UTF-8"?>
      <beans
          xmlns="http://www.springframework.org/schema/beans"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:util="http://www.springframework.org/schema/util"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:p="http://www.springframework.org/schema/p"
          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/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
      </beans>
      
    4. 编写目标类

      @Service
      public class PersonServiceImpl implements PersonService{
          @Autowired
          private PersonDao dao;
          @Override
          public void savePerson(Person person) {
              dao.savePerson(person);
          }
      
      }
      
    5. 编写切面和通知

      @Component
      public class TxAspect {
          @Autowired
          private TXManage tx;
          public Object around(ProceedingJoinPoint  pjp) throws Throwable{
              tx.startTx();
              pjp.proceed();
              tx.commti();
              return null;
          }
      }
      
    6. 配置切面表达式

      <!-- 配置切面 -->
      <aop:config>
          <!-- 配置切入点   一定要在切面的上面配置-->
          <!-- within表达式只能过滤包和类 -->
          <aop:pointcut expression="within(com.tj.service.*)" id="pc"/>
      </aop:config>
      
    7. 配置切面和通知

      <!-- 配置切面 -->
      <aop:config>
          <!-- 配置切入点   一定要在切面的上面配置-->
          <!-- within表达式只能过滤包和类 -->
          <aop:pointcut expression="within(com.tj.service.*)" id="pc"/>
          <!-- 配置切面 -->
          <aop:aspect ref="txAspect" >
              <!-- 配置切面中的通知 -->
              <aop:around method="around" pointcut-ref="pc"/>
          </aop:aspect>
      </aop:config>
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值