动态代理(AOP)

第一章 动态代理  
什么是动态代理?
代理模式在 Java 领域很多地方都有应用,它分为静态代理和动态代理,其中 Spring AOP 就是动态代理的典型例子。动态代理又分为接口代理和 cglib (子类代理)。

代理模式在我们日常中很常见,生活处处有代理:

看张学友的演唱会很难抢票,可以找黄牛排队买
嫌出去吃饭麻烦,可以叫外卖
无论是黄牛、外卖骑手都得帮我们干活。但是他们不能一手包办(比如黄牛不能帮我吃饭),他们只能做我们不能或者不想做的事。

找黄牛可以帮我排队买上张学友的演唱会门票
外卖骑手可以帮我把饭送到楼下
所以,你看。代理模式其实就是当前对象不愿意做的事情,委托给别的对象做。

 为什么要使用动态代理?
1.分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
2.减少代码的重复,各个模块的重用性加强。
3.降低 模块间的耦合度,提高代码的可操作性和可维护性。
如果我们不适用AOP,那么必然会导致项目中的日志与具体的业务逻辑都写在一起,而且是每一个接口里面都需要日志,那么日志的代码数量远远超过具体业务逻辑代码,这样不利于后期的维护已修改。同时违背了软件设计的思想。如果使用的AOP,我们把这种不是必然需要的同时也是服务具体业务的模块单独分装起来,在业务逻辑前或后直接调用,从而提高代码的可操作性和可维护性。

第二章  AOP
 什么是AOP?
AOP(Aspect Oriented Programming)即面向切面编程,是一种编程思想和技术。在传统的编程中,我们会将系统的业务逻辑分散在各个模块或类中,导致代码重复、难以维护。而 AOP 则通过将系统的横切关注点(如日志、事务、安全等)抽取出来,形成一组切面,然后将这些切面应用到系统中的多个模块或类中,从而实现了代码的复用和解耦。

AOP 相关术语
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。
Target(目标对象):代理的目标对象。
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类。
Aspect(切面):是切入点和通知(引介)的结合。
 下面我们来通过一个案例再深入了解一下AOP:
首先,导入IOC和AOP所需要的jar包
 

 然后,创建 BookService实体类和BookServiceImpl类继承实体类,实现方法,完成核心功能操作
public interface BookService {
    void findAll();
    void save(int a);
    int del();
    void update();
}
public class BookServiceImpl implements BookService {
    /**
     * 核心类
     */
    @Override
    public void findAll() {
        System.out.println("查询所有");
    }
 
    @Override
    public void save(int a) {
        System.out.println("保存信息"+a);
    }
 
    @Override
    public int del() {
        System.out.println("删除信息");
        return 5;
    }
 
    @Override
    public void update() {
        System.out.println("修改信息");
    }
}
其次,创建 Logger 类,这个类是用来做功能的增强。
public class Logger {
    /**
     * 增强类
     */
    public void check(){
        System.out.println("前置通知/增强:权限验证");
    }
    public void logPrint(){
        System.out.println("后置通知/增强:日志输出");
    }
    public void exception(){
        System.out.println("异常通知/增强:异常处理");
    }
    public void distory(){
        System.out.println("最终通知/增强:资源释放");
    }
}
然后,在 spring 的 beans.xml中开始进行 AOP 的配置:
首先把核心类和增强类的 bean 配置到IOC 的容器中使用<aop:config>标签在进行 AOP 的配置,先通过 aopaspect 标签标明谁是增强类。然后在标签中进行 aop:before ( 前置)、aop:after-returning (后置)、aop;after-throwing(异常)、aop:after (最终) 的配置,让增强类的某个方法对核心功能类的某一类方法进行功能增强。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--1.把所有类的对象交给IOC容器进行管理-->
    <bean id="logger" class="com.zy.logger.Logger" />
    <bean id="bookService" class="com.zy.service.impl.BookServiceImpl" />
 
    <!--2.AOP的配置:让增强类  动态的增强  核心类-->
    <aop:config>
        <!--指定增强类并且起个名字-->
        <aop:aspect id="check" ref="logger">
            <!--前置通知/增强:在核心类方法执行之前 进行  增强-->
            <aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after-returning method="logPrint" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after-throwing method="exception" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after method="distory" pointcut="execution(* *..BookServiceImpl.*(..))"/>
        </aop:aspect>
    </aop:config>
    </beans>
最后,在测试类中测试 BookServlet的方法是否被增强。

public class BookServlet {
    public static void main(String[] args) {
//        加载配置
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//        获取代理对象
        BookService bookService = context.getBean(BookService.class);
        bookService.findAll();
        bookService.save(2);
        bookService.del();
        bookService.update();
 
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值