spring AOP开发和JDBC


今天主要学习AOP的概念,简单地说,AOP将业务逻辑的各个部分进行隔离,采用横向抽取的机制,对模块间进行解耦,能有效提高开发效率。然后学习如何进行手动及spring进行AOP开发,利用spring进行AOP开发时,可以选择基于xml配置的方式或基于注释的方式实现AOP。基于注释的方式实现 AOP 的效果是最方便的方式,所以实际开发中推荐使用注解的方式。最后,基于昨天学习的配置数据源的基础上,学习了spring提供的JDBC Template的配置和基本CRUD操作的使用,JDBC模板可以对不同的数据源进行封装,并为用户提供了统一的大量的查询和更新数据库的方法,如 query()、update() 等,方便开发。

AOP简介

AOP相关概念

  • AOP 的全称是“Aspect Oriented Programming”,即面向切面编程,AOP和面向对象编程(OOP)类似,也是一种编程模
  • Spring AOP 是基于 AOP 编程模式的一个框架,它的使用有效减少了系统间的重复代码,达到了模块间的松耦合目的。它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率
  • AOP 采取横向抽取机制取代了传统纵向继承体系的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面
  • 目前最流行的 AOP 框架有两个,分别为 Spring AOP 和 AspectJ。Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入
  • AOP作用及优势
    • 在程序运行期间,在不修改代码的情况下,对方法进行功能增强
    • 减少重复代码,提高开发效率,并且便于维护
  • AOP底层实现
    • AOP的底层是通过spring提供的动态代理技术实现的。在运行期间,spring通过动态代理技术动态地生成代理对象,代理对象方法执行时进行功能增强的介入,去调用目标对象的代方法,从而实现功能增强

AOP术语

为了更好地理解 AOP,就需要对 AOP 的相关术语有一些了解,这些专业术语主要包含 Joinpoint(spring中就是指方法)、Pointcut、Advice、Target、Weaving、Proxy 和 Aspect,它们的含义如下表所示:
在这里插入图片描述

AOP常用动态代理技术

  • JDK代理:基于接口的动态代理技术
  • cglib代理:基于父类的动态代理技术
    在这里插入图片描述

手写JDK动态代理示例

  • 创建目标接口并定义实现类
    package com.example.proxy.jdk;
    
    public interface TargetInterface {
         
        public void save();
    }
    
    // --------------------------------------
    package com.example.proxy.jdk;
    
    public class TargetInterfaceImpl implements TargetInterface{
         
        @Override
        public void save() {
         
            System.out.println("save running");
        }
    }
    
  • 定义增强类,类的方法为增强目标对象的方法
    package com.example.proxy.jdk;
    
    public class Advice {
         
        public void before(){
         
            System.out.println("前置增强");
        }
    
        public void after(){
         
            System.out.println("后置增强");
        }
    }
    
  • 定义测试类,调用jdk代理方法,代理目标对象,并进行方法增强
    package com.example.proxy.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class JdkTest {
         
        public static void main(String[] args) {
         
            // 创建目标对象
            TargetInterfaceImpl target = new TargetInterfaceImpl();
            // 增强对象
            Advice advice = new Advice();
    		// 生成动态代理对象
            TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), // 目标对象加载器类
                    target.getClass().getInterfaces(),  // 与目标对象相同的接口字节码对象数组
                    new InvocationHandler() {
         
                        // 调用代理对象的任何方法,实质执行都是invoke方法
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         
                            // 前置增强
                            advice.before();
                            Object ret = method.invoke(target, args);// 执行目标方法
                            // 后置增强
                            advice.after();
                            return ret;
                        }
                    }
            );
    
            // 调用代理对象的方法,实质调用的是invoke,所以具有前置、后置增强效果
            proxy.save();
        }
    }
    

手写cglib动态代理示例

  • 直接定义目标类,cglib是基于父类的,不需要像Jdk代理一样定义接口
    package com.example.proxy.cglib;
    
    
    public class Target {
         
        public void save() {
         
            System.out.println("save running");
        }
    }
    
  • 增强类与Jdk代理一致
  • 定义测试类,使用cglib代理方法,对目标进行增强
    package com.example.proxy.cglib;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    
    public class CglibTest {
         
        public static void main(String[] args) {
         
            // 创建目标对象
            Target target = new Target();
            // 增强对象
            Advice advice = new Advice();
            // 基于cglib,生成动态代理对象
            // 1. 创建增强器
            Enhancer enhancer = new Enhancer();
            // 2. 设置父类(目标)
            enhancer.setSuperclass(Target.class);
            // 3. 设置回调
            enhancer.setCallback(new MethodInterceptor() {
         
                // 与jdk代理中的invoke类似
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
         
                    // 执行前置增强
                    advice.before();
                    // 执行目标
                    Object invoke = method.invoke(target, args);
                    // 执行后置增强
                    advice.after();
                    return invoke;
                }
            });
            // 4. 创建代理对象,cglib基于父类的,代理是Target的子类对象
            Target proxy = (Target) enhancer.create();
    
            // 调用增强后的方法
            proxy.save();
        }
    }
    

spring进行AOP开发事项

  • 需要编写的内容
    • 编写核心业务代码(目标类的目标方法)
    • 编写切面类,切面类中有通知(增强功能方法)
    • 在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合
  • AOP技术实现的内容
    • spring框架监控切入点方法的执行,一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能切入,完成完整的代码逻辑运行。
  • AOP底层使用哪种代理方式
    • spring框架会根据目标类是否实现了接口来决定采用哪种动态代理方式

基于XML的AOP开发

切点表达式

  • 切点表达式语法execution([修饰符] 返回类型 包名.类名.方法名(参数))
    • 访问修饰符可以省略
    • 返回值类型、包名、类名、方法名可以使用*代表任意
    • 包名与类名之间一个点.代表当前包下的类,两个点… 代表当前包及其子包下的类
    • 参数列表可以使用两个点… 表示任意个数、任意类型的参数列表

通知配置语法及类型

在这里插入图片描述

开发步骤

  • 导入AOP相关坐标
  • 创建目标接口和目标类(内部须有切点)
  • 创建切面类(内部有增强方法)
  • 将目标类和切面类的对象创建权交给spring
  • 在applicationContext.xml文件中配置织入关系
  • 测试代码

开发示例

  • pom.xml导入AOP相关坐标,使用aspectj开发AOP
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.6</version>
    </dependency>
    
  • 创建目标接口和目标类
    package com.example.aop;
    
    // 目标接口
    public interface TargetInterface {
         
        public void save();
    }
    // ----------------------------------
    package com.example.aop;
    
    
    // 目标类
    public class Target{
         
        public void save() {
         
            System.out.println("save running");
        }
    }
    
  • 创建切面类(内部有增强方法)
    package com.example.aop;
    // 创建切面类
    public class MyAspect {
         
        public void before(){
         
            System.out.println("前置增强");
        }
    
        public void after(){
         
            System.out.println("后置增强");
        }
    }
    
  • 将目标类和切面类的对象创建权交给spring,需要导
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值