欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

第三章 AOP面向切面编程

程序员文章站 2022-03-22 10:25:21
第三章 AOP 面向切面编程3.1 动态代理3.2 AOP 概述3.3 AOP 简介3.4 AOP 编程术语3.1 动态代理可以在程序的执行过程中,创建代理对象。通过代理对象执行方法,给目标类增加额外的功能而不改变原来类中的代码(功能增强)1、JDK 动态代理:要求目标对象必须实现接口,通过 java.lang.reflect 包提供三个类支持代理模式 Proxy、Method 和 InvocationHandler 。实现步骤:1)创建目标类(如果目标类已经存在,此步骤可以省略)2)创...

第三章 AOP 面向切面编程

3.1 动态代理
3.2 AOP 概述
3.3 AOP 编程术语
3.4 AOP 的实现

3.1 动态代理

可以在程序的执行过程中,创建代理对象。通过代理对象执行方法,给目标类增加额外的功能而不改变原来类中的代码(功能增强),在一定程度上减少代码重复。

1、JDK 动态代理:要求目标对象必须实现接口,通过 java.lang.reflect 包提供三个类支持代理模式 Proxy、Method 和 InvocationHandler 。

实现步骤:
1)创建目标类(如果目标类已经存在,此步骤可以省略)

	SomeService,SomeServiceImpl(目标类,实现 SomeService 接口)

2)创建 InvocationHandler 接口的实现类,在这个类实现给目标方法增加功能

public class MyInvocationHandler implements InvocationHandler {
	// 目标对象
	private Object target; 

	public MyInvocationHandler (Object target) {
		this.target = target;
	}
	
	// 通过代理对象执行方法时,会调用这个invoke()
	// 在这个方法里添加需要增加的功能
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object res = null;
		// 可以在目标方法前添加
		// xxxx 要增加的功能
		// 执行目标类的方法,通过 Method 类实现
		res = method.invoke(target,args);
		// 也可以在目标方法后添加
		// xxxx 要增加的功能
		return res;
	}
}

3)使用 jdk 中的类 Proxy 创建代理对象,实现创建对象的能力

// 创建目标对象
SomeService target = new SomeServiceImpl();

// 创建 InvocationHandler 对象
InvocationHandler handler = new MyInvocationHandler(target );

// 使用 Proxy 创建代理
SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);

// 通过代理执行方法,会调用 handler 中的 invoke()
// doSome() 是 SomeService 中的方法,在 SomeServiceImpl 中被实现
proxy.doSome();

2、CGLIB 动态代理:第三方工具库,创建代理对象。原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象,所以要求目标类必须能够被继承,即不能是 final 类。

3.2 AOP 概述

1、Aop是什么?

Aop 是基于动态代理,可以使用 jkd,cglib 两种代理方式。Aop 就是动态代理的规范化,把动态代理的实现步骤、方式都定义好了,让开发人员用一种统一的方式去使用动态代理。

2、怎么理解面向切面编程

AOP(Aspect Orient Programming)
Aspect :切面,给目标类增加的功能就是切面,比如日志、事务、统计信息、参数检查、权限限定都是切面。切面一般都是非业务方法,独立使用。
Orient :面向
Programming:编程

1)在分析项目功能时,需要找出切面
2)合理的安排切面的执行时间(在目标方法前还是目标方法后)
3)合理的安排切面的执行位置(在哪个类,在哪个方法)

3.3 AOP 编程术语

1)Aspect
2)JoinPoint:连接点,程序执行的某一个特定位置,如类初始前后,方法的运行前后,而 Spring 只支持方法的连接点
3)Pointcut:切入点,切点是匹配了一个或多个连接点。定义了切面在何处执行,切点的前提也是一个连接点,它是连接点的一个子集
4)Advice:通知,定义了切面是什么以及何时使用,Spring 中的通知有以下5种:

	前置通知(before):在目标方法执行之前执行的通知
	后置通知(after):在目标方法执行之后执行的通知,此时不关心方法是否成功执行
	返回通知(after-returning):在目标方法成功执行之后执行的通知
	异常通知(after-throwing):在目标方法抛出异常之后执行的通知
	环绕通知(around):通知包含了目标方法,可以在目标方法执行之前和执行之后执行自定义的行为。
以上五种分别对应 AspectJ 中的通知注解:@Before、@After、@AfterRunning、@AfterThrowing、@Around
	
5)Target:目标对象,给哪个类的方法增加功能,这个类就是目标对象

3.4 AOP 的实现

spring:spring 在内部实现了 aop 规范,能完成 aop 的工作,主要在事务处理时使用 aop,但我们在项目开发中很少使用 spring 框架中的 aop,因为其比较笨重。

aspectJ:是一个开源专门做 aop 的框架,spring 的框架中集成了 aspectJ 框架,有两种使用方式:
	1)xml 配置文件:配置全局事务
	2)注解:通常使用此种方式实现

使用 aspectJ 实现 aop 的基本步骤:

1)新建 maven 项目
2)添加 spring 和 aspectJ 依赖
3)创建目标类:接口和它的实现类
4)创建切面类:普通类
   在类的上面加入 @Aspect;在类中定义方法,方法就是切面要执行的功能代码;在方法上面加入 AspectJ 中的通知注解;指定切入点表达式 execution()
5)创建 spring 的配置文件:声明对象,把对象交给容器统一管理
	a、声明目标类对象
	b、声明切面类对象
	c、声明 aspect 框架中的自动代理生成器(用来完成代理对象的自动创建功能)标签,以下使用 Proxy 创建代理这步就可省略
6)从 spring 容器中获取目标对象(实际就是代理对象),通过代理执行方法,实现 aop 的功能增强
// spring 依赖
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.5.RELEASE</version>
</dependency>

// aspectj 依赖
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
	<version>5.2.5.RELEASE</version>
</dependency>
/*
* @Aspect :是 Aspectj 框架中的注解
* 作用:表示当前类是切面类
* 切面类:用来给业务方法增加功能的类
* 位置:定义在类的上面
*/
@Aspect
public class MyAspect {
	/*
	* 定义方法,用来实现切面功能
	* 方法的定义要求:
	* 1、必须是公共方法(public)
	* 2、方法没有返回值(void)
	* 3、方法的名称自定义
	* 4、方法可以有参数也可以没有参数
	*/
	
	/* 
	* 此处以 @Before 注解为例 
	* 位置:定义在方法上面
	* 特点:
	* 1、在目标方法之前执行
	* 2、不会改变目标方法的执行结果
	* 3、不会影响目标方法的执行
	*/
	
	@Before(value="execution(public void 包名.类名.方法名(参数) 异常)")
	public void myBefore() {
	}
}
// 声明目标对象
<bean id="someService" class="xxx" />

// 声明切面对象
<bean id="myAspect" class="xxx" />

/* 声明自动代理生成器:使用 aspectj 框架内部的功能,创建目标对象的代理对象
* 创建代理对象是在内存中实现的,修改目标对象在内存中的结构,创建为代理对象,
* 所以目标对象就是被修改后的代理对象
*/
// aspectj-autoproxy 会把 spring 容器中的所有目标对象一次性都生成代理对象
<aop:aspectj-autoproxy />

// 以下这步可以省略
// 使用 Proxy 创建代理
SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);

第二章 IoC控制反转

本文地址:https://blog.csdn.net/qq_39171225/article/details/109517124