Spring AOP及JDK动态代理介绍 - 极悦
首页 课程 师资 教程 报名

Spring AOP及JDK动态代理介绍

  • 2022-07-04 11:33:45
  • 1464次 极悦

什么是AOP

AOP的全称是面向方面编程,即面向方面编程。它是面向对象编程(OOP)的补充。目前已经成为一种比较成熟的编程方式。

在传统的业务处理代码中,通常会进行事务、日志等操作。虽然使用OOP可以通过组合或者继承来实现代码复用,但是如果要实现一个功能(比如日志),同样的代码还是会分散在各种方法中。这样,如果你想关闭一个功能或者修改它,你必须修改所有相关的方法。这不仅增加了开发者的工作量,也提高了代码的错误率。

为了解决这个问题,AOP的想法应运而生。AOP采用横向抽取机制,将分散在各种方法中的重复代码抽取出来,然后在程序编译或运行时将抽取出来的代码应用到需要执行的地方。采用横向抽取机制和传统的OOP思想显然是不可能的,因为OOP只能实现父子关系的纵向复用。虽然 AOP 是一种新的编程思想,但它并不能替代 OOP。它只是OOP的扩展和补充。

AOP 在编写业务逻辑时,开发人员可以专注于核心业务,而不必过多关注其他业务逻辑的实现,不仅提高了开发效率,还增强了代码的可维护性。

目前最流行的AOP框架有两种:spring AOP和AspectJ。Spring AOP 是用纯 Java 实现的,没有特殊的编译过程和类加载器。增强代码在运行时通过代理编织到目标类中。AspectJ 是一个基于 Java 语言的 AOP 框架,从 spring 2.0 开始,spring AOP 引入了对 AspectJ 的支持,它扩展了 Java 语言,并提供了一个特殊的编译器,在编译时提供横向代码编织。

AOP术语

Aspect:在实际应用中,Aspect通常是指用于横向插入系统功能(如事务、日志等)的封装类。要被Spring容器识别为切面,需要通过配置文件中的元素来指定。

Joinpoint:在程序执行过程中的某个阶段,实际上是对一个对象的操作,比如方法调用或者异常抛出。在 Spring AOP 中,连接点是一个方法调用。

切入点:指切面与程序流的交集,即需要处理的连接点。通常在程序中,切入点是指类或方法名。如果要对所有以 add 开头的方法应用通知,则所有符合该规则的方法都是切入点。

Advice:AOP框架在特定切入点处进行的增强处理,即在定义的切入点处要执行的程序代码。可以理解为切面类中的方法,是切面的具体实现。

目标对象:指所有被通知的对象,也称为增强对象。如果AOP框架采用动态AOP实现,那么对象就是代理对象。

代理:通知应用到目标对象后动态创建的对象。

编织:将切片代码插入目标对象以生成代理对象的过程。

JDK的动态代理

1.创建web工程,将Spring框架需要的JAR包导入到工程lib目录下,发布到类路径下。

2.在src目录下,创建一个包(比如我创建的yjf.jdk),在包下创建接口UserDao.java

包yjf.jdk;
公共接口 UserDao {
	公共无效添加用户();
	公共无效删除用户();
}

3.在yjf.jdk包中,创建UserDao接口实现的类UserDaoImpl.java,分别实现接口中的方法

包yjf.jdk;
公共类 UserDaoImpl 实现 UserDao {
	公共无效添加用户(){
		System.out.println("添加用户");
	}
	公共无效删除用户(){
		System.out.println("删除用户");
	}		
}

4.在src目录下再创建一个包(比如我创建的yjf.aspect包),在包下创建切面类MyAspect.java。在这个类中,定义一个检查模拟权限的方法和一个模拟日志记录的方法。这两个方法是方面的通知

包yjf.aspect;
公共类 MyAspect {
	公共无效 check_Permissions(){
		System.out.println("模拟检查权限......");
	}
	公共无效日志(){
		System.out.println("模拟日志......");
	}
}

5.在yjf.jdk包下,创建Proxy类JdkProxy,需要实现InvocationHandler接口,编写Proxy方法。在Proxy方法中,需要通过Proxy类实现动态Proxy

包yjf.jdk;
导入 java.lang.reflect.InvocationHandler;
导入java.lang.reflect.Method;
导入 java.lang.reflect.Proxy;
导入 yjf.aspect.*;
/* JDK 代理类 */
公共类 JdkProxy 实现 InvocationHandler {
	//声明目标类接口
	私人用户道用户道;
	//创建代理方法
	公共对象 createProxy(UserDao userDao){
		this.userDao = userDao;
		//1. 类加载器
		类加载器 classLoader = JdkProxy.class.getClassLoader();
		//2。代理对象实现的所有接口
		类[] clazz = userDao.getClass().getInterfaces();
		//3. 使用代理类增强代理后返回对象
		return Proxy.newProxyInstance(classLoader, clazz, this);
	}
	/*
	 * 动态代理类的所有方法调用都由invoke()方法处理
	 * 被表示后的代理对象
	 * method 要执行的方法信息(反射)
	 * asgs 执行方法所需的参数
	 *
	 * */
	@覆盖
	public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
		//声明部分
		MyAspect myAspect = new MyAspect();
		//预增强
		myAspect.check_Permissions();
		//调用目标类上的方法并传入参数
		对象 obj = method.invoke(userDao, args);
		//侯增强
		myAspect.log();
		返回对象;
	}
}

6.在yjf.jdk包中,创建测试类JdkTest,在该类中创建代理对象和目标对象,然后从代理对象中获取目标对象userDao增强的对象,最后调用add和delete方法在对象中。

包yjf.jdk;
公共类 JdkTest {
	公共静态无效主要(字符串[]参数){
		//创建代理对象
		JdkProxy jdkProxy = new JdkProxy();
		//创建目标对象
		UserDao userDao = new UserDaoImpl();
		//从代理对象中获取增强的目标对象
		UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
		//执行方法
		userDao1.addUser();
		userDao1.deleteUser();
	}
}

运行结果为:

模拟检查权限......
添加用户
 模拟日志……
模拟检查权限......
删除用户
 模拟日志……

可以看到userDao实例中添加和删除用户的方法已经成功调用,调用前后增加了查看权限和记录权限的功能。这是 Spring动态代理

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交