SpringAOP 相关

本贴最后更新于 1749 天前,其中的信息可能已经时移世易

Spring 的 AOP

AOP 思想介绍

Spring 中的 aop 概念

Spring 实现 aop 的原理

动态代理(优先)

被代理对象必须要实现接口,才能产生代理对象。如果没有接口将不能使用动态代理技术

cglib 代理(没有接口)

第三方代理技术,cglib 代理。可以对任何类生成代理。代理的原理是对目标对象进行继承代理。 如果目标对象被 final 修饰。那么该类无法被 cglib 代理。

aop 名词学习

1.导 AOP 相关的 jar 包

  • spring-aspects-4.2.4.RELEASE.jar
  • spring-aop-4.2.4.RELEASE.jar
  • com.springsource.org.aopalliance-1.0.0.jar
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

2.准备目标对象

package com.tobeshrek.test.aop.service;
/**
 * AOP测试service层
 * @author 李国豪
 * @date:2020年1月13日
 */
public interface UserService {
	void save();
	void update();
}
package com.tobeshrek.test.aop.service.impl;

import com.tobeshrek.test.aop.service.UserService;
/**
 * 测试接口实现类
 * @author 李国豪
 * @date:2020年1月13日
 */
public class UserServiceImpl implements UserService {
	@Override
	public void save() {
		System.out.println("保存用户!");
	}
	@Override
	public void update() {
		@SuppressWarnings("unused")
		int i = 1/0;//测试异常流程
		System.out.println("更新用户!");
	}
}

3.准备通知

package com.tobeshrek.test.aop.advice;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * AOP测试通知
 * @author 李国豪
 * @date:2020年1月13日
 */
public class MyAdvice {
	//前置通知
	public void before(){
		System.out.println("这是前置通知!!");
	}
	//后置通知(如果出现异常不会调用)
	public void afterReturning(){
		System.out.println("这是后置通知(如果出现异常不会调用)");
	}
	//环绕通知
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("这是环绕通知之前的部分!!");
		Object proceed = pjp.proceed();//调用目标方法
		System.out.println("这是环绕通知之后的部分!!!");
		return proceed;
	}
	//异常通知
	public void afterException(){
		System.out.println("这是出现异常提示的通知!!");
	}
	//后置通知(无论是否出现异常都会调用)
	public void after(){
		System.out.println("这是后置通知(出现异常也会调用!!)");
	}
}

4.配置进行织入,将通知织入目标对象中

<!-- 准备工作:导入aop(约束)命名空间 -->							
	<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.tobeshrek.test.aop.service.impl.UserServiceImpl"></bean>
	<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="com.tobeshrek.test.aop.advice.MyAdvice"></bean>
	<!-- aop配置 -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(* com.tobeshrek.test.aop.service.impl.*ServiceImpl.*(..))" id="pc"/>
		<!-- 切面 -->
		<aop:aspect ref="myAdvice" >
			<!-- 指定名为before方法最为前置通知 -->
			<aop:before method="before" pointcut-ref="pc"/>
			<!-- 后置通知,出现异常不调用 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pc" />
			<!-- 异常拦截通知 -->
			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
			<!-- 后置通知,出现异常仍然调用 -->
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>

5.测试

//加载spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");	UserService userService = ac.getBean(UserService.class);
//userService.save();//正常的流程
userService.update();//异常的流程

6.结果

  • 正常的流程
这是前置通知!!
这是环绕通知之前的部分!!
保存用户!
这是后置通知(出现异常也会调用!!)
这是环绕通知之后的部分!!!
这是后置通知(如果出现异常不会调用)
  • 异常的流程
这是前置通知!!
Exception in thread "main" 这是环绕通知之前的部分!!
这是后置通知(出现异常也会调用!!)
这是出现异常提示的通知!!
java.lang.ArithmeticException: / by zero
	at com.tobeshrek.test.aop.service.impl.UserServiceImpl.update(UserServiceImpl.java:17)

总结

使用时应该注意:正常执行的话一切都没问题,出现异常的时候环绕通知之后的部分后置异常不调用通知内的代码不会执行

总结的流程图如下

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 31 关注
  • AOP
    21 引用 • 13 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...