SpringAOP知识内容梳理

本文详细介绍了Spring AOP的核心概念,包括连接点、切入点、通知、目标对象、织入和代理等,并阐述了Spring AOP的两种实现机制——JDK动态代理和CGLib动态代理。在JDK代理中,代理类需实现InvocationHandler接口,而CGLib则是通过字节码技术动态创建代理对象。此外,还讨论了基于XML和注解的AOP配置方式,以及相关元素的用途。
摘要由CSDN通过智能技术生成

一、SpringAOP的概念及术语

1.JoinPoint(连接点): 目标对象中,所有<可以增强>的方法,叫做连接点
2.Pointcut(切入点): 目标对象中,所有<已经增强>的方法,叫做切入点
3.Advice(通知):
1.<增强>的代码
2.所谓通知就是拦截到JoinPoint之后做的事情就是通知
通知又包括
a.前置通知(目标方法运行前通知)
b.返回通知(目标方法运行后通知)
c.异常通知(出现异常时会调用)
d.后置通知(无论是否异常都会调用,目标方法运行后调用)
e.环绕通知(目标方法运行前后通知)
4.Target(目标对象): 代理的对象(被代理的对象)
5.Weaving(织入): 将通知应用到切入点的过程
6.Proxy(代理): 将通知应用到目标对象后形成的代理对象
7.Aspect(切面): 通知和切入点的结合
8.Introduction(引介): 引介是一种特殊的通知,它可以为目标对象添加一些属性和方法。

二、SpringAOP的实现机制

SpringAOP实现时需要创建一个代理对象,根据代理对象的创建方式,可以将AOP实现机制分为两种,一种是JDK动态代理,另一种是CGLib动态代理。

1.JDK动态代理

默认情况下,Spring AOP使用JDK动态代理,JDK动态代理是通过java.lang.reflect.Proxy类实现的,可以调用Proxy类newProxyInstance()方法创建代理对象。 JDK动态代理可以实现无侵入式的代码扩展,并且可以在不修改源代码的情况下增强某些方法。
首先需要创建一个代理类,该类需要实现InvocationHandler接口设置代理类的调用处理程序。具体实现为下图:
//JDK动态代理
public class UserServiceFactory implements InvocationHandler {
//声明目标类接口
private UserService userService;

//使用构造方法获取目标类
public UserServiceFactory(UserService userService) {
this.userService = userService;
}

public UserServiceFactory() {
}

//代理方法
public Object createProxy(){

//类加载器
ClassLoader classLoader = UserServiceFactory.class.getClassLoader();
//被代理对象实现的接口
Class[] classes = UserImp.class.getInterfaces();
//使用代理类进行增强
UserService us = (UserService) Proxy.newProxyInstance(classLoader, classes,this);
return us;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//业务之前的方法--前增强
System.out.println("--------开起事务---------");//切入点
//目标类上调用方法,并传参数
Object invoke = method.invoke(userService, args);
//业务之后的方法--后增强
System.out.println("--------关闭事务---------");
return invoke;
}
}

获取增强后的目标对象方法如下:

//测试JDK动态代理
//只能为接口创建代理对象
@Test
public void text1(){
//获取到接口对象
UserService userService = new UserImp();
//获取动态代理对象
UserServiceFactory factory = new UserServiceFactory(userService);
//获取代理对象
UserService service = (UserService) factory.createProxy();//从代理对象对象中获取增强后的目标对象
service.find();
}

2.CGLib动态代理

JDK动态代理存在缺陷,它只能为接口创建代理对象,当需要为类创建代理对象时,就需要使用CGLib(Code Generation Library)动态代理,CGLib动态代理不要求目标类实现接口,它采用底层的字节码技术,通过继承的方式动态创建代理对象。Spring的核心包已经集成了CGLib所需要的包,所以不需要再导入。其实现如下图:

//CGLib代理类
public class UserServiceFactorys implements MethodInterceptor {

//代理方法
public Object createProxy(Object target){

//创建一个动态类对象
Enhancer enhancer = new Enhancer();

//将接收的对象进行增强,设置其父类
enhancer.setSuperclass(target.getClass());

//添加回调函数
enhancer.setCallback(this);

return enhancer.create();
}

@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//业务之前的方法--前增强
System.out.println("--------开起事务---------");//切入点
//目标类上调用方法,并传参数
Object invoke = methodProxy.invokeSuper(o, objects);
//业务之后的方法--后增强
System.out.println("--------关闭事务---------");
return invoke;
}
}

获取增强后的目标对象方法如下:

//测试CGLib动态代理
//可以为类创建代理对象
@Test
public void text2(){
//获取到目标类对象
UserImp user= new UserImp();
//获取动态代理对象
UserServiceFactorys factory = new UserServiceFactorys();
//获取代理对象
UserImp service = (UserImp) factory.createProxy(user);//从代理对象对象中获取增强后的目标对象
service.find();
}

三、基于XML的AOP实现

XML实现AOP切面,其包括以下的元素:

<aop:config>:SpringAOP配置的根元素;

<aop:aspect>:配置切面;

<aop:advisor>:配置通知器;

<aop:pointcut>:配置切入点;

<aop:before>:配置前置通知,在目标方法执行前实施增强,可以应用于权限管理等功能;

<aop:after>:配置后置通知,在目标方法执行后实施增强,可以应用于关闭流、上传文件、 删除临时文件等功能;

<aop:around>:配置环绕通知,在目标方法执行前后实施增强,可以应用于日志、事务管理功能;

<aop:after-returning>:配置返回通知,在目标方法执行之后调用通知;

<aop:after-throwing>:配置异常通知,在方法抛出异常后实施增强,可以应用于处理异常记录日志等功能;

其实现如下:

<!--将通知织入到目标对象中-->
<!--1.配置目标对象-->
<bean name="user" class="com.jay.Service.UserImp"></bean>
<!--2. 配置通知对象-->
<bean name="advice" class="com.jay.advice.Advice"></bean>
<!--3.将对象织入目标对象中-->
<aop:config>
<!-- 3.1 配置切入点-->
<!-- 通配符 -->
<!--
public void com.jay.Service.UserImp.find()
* com.jay.Service.UserImp.find()
* com.jay.Service.*Imp.find()字段用*表示
* com.jay.Service.*Imp.*(..)参数用“..”表示;方法同字段一样用*表示
-->
<aop:pointcut id="pt" expression="execution(* com.jay.Service.UserImp.*())"/>
<!-- 3.2 指定通知-->
<aop:aspect ref="advice">
<aop:before method="getBefore" pointcut-ref="pt"></aop:before>
<aop:after-returning method="getAfter" pointcut-ref="pt"></aop:after-returning>
<aop:around method="getAround" pointcut-ref="pt"></aop:around>
<aop:after-throwing method="getException" pointcut-ref="pt"></aop:after-throwing>
<aop:after method="getLastException" pointcut-ref="pt"></aop:after>
</aop:aspect>
</aop:config>

四、基于注解的AOP实现

@Aspect:配置切面

@Pointcut:配置切入点

@Before:配置前置通知

@After:配置后置通知

@Around:配置环绕通知

@AfterReturning:配置返回通知

@AfterThrowing:配置异常通知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值