基于代理类的AOP的实现

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于代理类的AOP的实现相关的知识,希望对你有一定的参考价值。

基于代理类的AOP的实现

  • 在spring中默认使用JDK动态代理实现AOP编程,使用代理类创建代理是SpringAOP实现的最基本的方式
  • 根据Spring中通知在目标方法中的连接点的位置,通知可以分为下面6种类类型
  • 1-环绕通知:在目标方法执行前和执行后实施增强,可以用于日志记录,事务处理。
  • 2-前置通知:在目标方法执行前实施增强,可以应用于权限管理等功能。
  • 3-后置返回通知:在目标方法执行后实施增强,可以用于关闭流,删除临时文件等。
  • 4-后置最终通知:在目标方法执行后实施增强,不管是否发生异常都要执行该类通知,该类通知可用于释放资源。
  • 5-异常通知:在方法抛出异常后实施增强,可以用于处理异常,记录日志等功能。
  • 6-引入通知:在目标类中添加一些新的方法和属性,可以应用于修改目标类。
  • ProxyFactoryBean是一个接口的实现类,FactoryBean负责实例化一个Bean实例,ProxyFactoryBean负责为其它Bean创建代理实例。
  • ProxyFactoryBean类的常用属性:
  • 1-target:代理的目标对象
  • 2-proxyInterfaces:代理需要实现的接口
  • 3-interceptorNames:需要织入目标的Advice
  • 4-proxyTargetClass:是否对类代理而不是接口,默认为false,使用JDK代理,当为true,使用CGLIB代理
  • 5-singleton:返回的代理实例是否为单例,默认为true
  • 6-optimize:当设置为true时候,强制使用CGLIB代理

本次使用的开发环境是IDEA
通过一个环绕通知的实例演示Spring使用ProxyFactoryBean创建AOP代理的过程.

1-使用IDEA创建Spring项目,库Libraries选择DownLoad,自当下载所需的jar包,无需导入
在这里插入图片描述
自动默认导入的jar包如下:
在这里插入图片描述
2-在src目录下创建包dynamic.jdk,并在该包中创建接口TestDao和接口的实现类TestDaoImpl.

public interface TestDao {
    public void save() ;
    public void modify() ;
    public void delete() ;
}


public class TestDaoImpl  implements TestDao {
    @Override
    public void save() {
        System.out.println("保存") ;
    }

    @Override
    public void modify() {
        System.out.println("修改") ;
    }

    @Override
    public void delete() {
        System.out.println("删除") ;
    }
}

3-在src目录创建包spring.proxyfactorybean包,并在该包中创建切面类MyAspect

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

//通过一个环绕通知的实例演示Spring使用ProxyFactoryBean创建AOP代理的过程
public class MyAspect implements MethodInterceptor {

    public void check(){
        System.out.println("模拟权限控制")  ;
    }
    public void except(){
        System.out.println("模拟异常处理") ;
    }
    public void log(){
        System.out.println("模拟日志记录") ;
    }
    public void monitor(){
        System.out.println("模拟性能监控") ;
    }
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable { //重写invoke接口方法
        //前增强
        check() ;
        except() ;
        //执行目标方法
        Object object = methodInvocation.proceed() ;
        //后增强
        log() ;
        monitor() ;
        return object;
    }
}

4-为切面类配置bean实例,是Spring容器识别切面对象

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--定义目标对象-->
    <bean id = "testDao" class = "dynamic.jdk.TestDaoImpl"/>
    <!--创建一个切面-->
    <bean id = "MyAspect" class = "spring.proxyfactorybean.MyAspect"/>
    <!--使用Spring代理工厂定义一个名为testDaoProxy的代理对象-->
    <bean id = "testDaoProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">
    <!--指定代理实现的接口-->
        <property name="proxyInterfaces" value = "dynamic.jdk.TestDao"/>
        <!--指定目标对象-->
        <property name = "target" ref = "testDao"/>
        <!--指定切面,织入环绕通知-->
        <property name = "interceptorNames" value = "MyAspect"/>
    </bean>
</beans>

5-在spring.proxyfactorybean包中创建测试类ProxyFactoryBeanTest测试类,在main方法中使用Spring容器获取增强后的目标对象,并执行目标方法。

import dynamic.jdk.TestDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 创建测试类,在主方法中使用Spring容器获取增强后的目标对象,并执行目标方法
 */
public class ProxyFactoryBeanTest {
    public static void main(String[] args){
        //初始化Spring容器,并加载配置文件
        ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml") ;
        //从容器中获取增强后目标对象
        TestDao testDaoAdvice = (TestDao) appCon.getBean("testDaoProxy");
        //执行方法
        testDaoAdvice.save() ;
        System.out.println("================") ;
        testDaoAdvice.modify()  ;
        System.out.println("================") ;
        testDaoAdvice.delete() ;
        System.out.println("================") ;
    }
}

6-测试结果入下:
在这里插入图片描述

以上是关于基于代理类的AOP的实现的主要内容,如果未能解决你的问题,请参考以下文章

基于代理类的AOP的实现

Spring------AOP

JAVA之AOP

spring aop中this和target区别

Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口

Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口