ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring AOP介绍和JDK的动态代理

2021-09-21 10:04:12  阅读:127  来源: 互联网

标签:userDao yjf JDK 对象 Spring 代理 AOP public


1.什么是AOP

       AOP的全称是Aspect-Oriented Programming,即面向切面的编程(面向方面编程)。它是面向对象编程(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的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入。

2.AOP术语

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

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

Pointcut(切入点):是指切面与程序流程的交叉点,即那些需要处理的连接点。通常在程序中,切入点指的是类或者方法名,如某个通知要应用到所有以add开头的方法中,那么所有满足这一规则的方法都是切入点。

Advice( 通知/增强处理 ):AOP 框架在特定的切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码。可以将其理解为切面类中的方法,它是切面的具体实现。

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

Proxy(代理):将通知应用到目标对象之后,被动态创建的对象。

Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程。

3.JDK的动态代理

1.创建一个web项目,导入Spring框架所需的JAR包到项目lib目录中,并发布到类路径下。

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

package yjf.jdk;

public interface UserDao {
	public void addUser();
	public void deleteUser();
}

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

package yjf.jdk;

public class UserDaoImpl implements UserDao {
	public void addUser(){
		System.out.println("添加用户");
	}
	public void deleteUser(){
		System.out.println("删除用户");
	}
		
}

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

package yjf.aspect;

public class MyAspect {
	public void check_Permissions(){
		System.out.println("模拟检查权限......");
	}
	public void log(){
		System.out.println("模拟记录日志......");
	}
}

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

package yjf.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import yjf.aspect.*;
/* JDK代理类 */
public class JdkProxy implements InvocationHandler {
	//声明目标类接口
	private UserDao userDao;
	//创建代理方法
	public Object createProxy(UserDao userDao){
		this.userDao = userDao;
		//1.类加载器
		ClassLoader classLoader = JdkProxy.class.getClassLoader();
		//2.被代理对象实现的所有接口
		Class[] clazz = userDao.getClass().getInterfaces();
		//3.使用代理类,进行增强,返回的是代理后的对象
		return Proxy.newProxyInstance(classLoader, clazz, this);
	}
	/*
	 * 所有动态代理类的方法调用,都会交由invoke()方法去处理
	 * proxy被代理后的对象
	 * method 将要被执行的方法信息(反射)
	 * asgs 执行方法时需要的参数
	 * 
	 * */
	@Override
	public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
		//声明切面
		MyAspect myAspect = new MyAspect();
		//前增强
		myAspect.check_Permissions();
		//在目标类上调用方法,并传入参数
		Object obj = method.invoke(userDao, args);
		//侯增强
		myAspect.log();
		return obj;
	}

}

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

package yjf.jdk;

public class JdkTest {
	public static void main(String[] args){
		//创建代理对象
		JdkProxy jdkProxy = new JdkProxy();
		//创建目标对象
		UserDao userDao = new UserDaoImpl();
		//从代理对象中获取增强后的目标对象
		UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
		//执行方法
		userDao1.addUser();
		userDao1.deleteUser();
	}
}

运行结果为:

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

可以看出,userDao实例中的添加用户和删除用户的方法已被成功调用,并且在调用前后分别增加了检查权限和记录日志权限的功能。这就是JDK动态代理。

标签:userDao,yjf,JDK,对象,Spring,代理,AOP,public
来源: https://blog.csdn.net/xing__he/article/details/120398444

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有