spring-实现AOP

AOP基本概念

  1. Aspect(切面):通常是一个类,里面可以定义切入点和通知
  2. JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
  3. Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
  4. Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
  • AOP代理:

    • AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
    • Procy代理:将通知应用到目标对象之后,被动态创建的对象。
    • Weaving织入:将切面代码插入到目标对象上,从而生成代理对象的过程
  • JDK动态代理:

    • JDK动态代理是通过java.lang.reflect.Proxy类来实现的,我们可以调用Proxy类的newProxyInstance(方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。
  • CGLIB代理:

    • CGLIB(Code Generation Library)是一个高性能开源的代码
      生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。
  • AOP的用途

    • 权限的校验
    • 日志的记录
    • 事务的处理
    • 性能的检测
  • AOP通知方法:

  1. 前置通知:在我们执行目标方法之前运行(@Before)
  2. 后置通知:在我们目标方法运行结束之后,不管有没有异常(@After)
  3. 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
  4. 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
  5. 环绕通知:动态代理,需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知(@Around)
  • 切点表达式:
    在这里插入图片描述

    • 修饰关键字:public private protectd,一般这个写*,表示不限定关键词
    • 返回值类型:int string Person void,一般省略不写(如果要写,修饰关键词不能*)
    • 切入点属于哪个包,配置包名,必须写完整的包名,不支持子包
    • 切入点属于哪个类,配置类名,如果*,表示不限定
    • 切入点是哪个方法,配置方法名
    • 切入点方法的参数,一般用两个点表示任意参数都可以
  • 几个例子:

  1. execution(public * *(…)) :

    • pulbic开头的任意包的任意类的任意方法,任意返回值,任意参数
  2. execution(* set*(…)):

    • 任意修饰的任意包的任意类的以set开头的方法,任意返回值,任意的参数
  3. execution(* com.xyz.service.AccountService.*(…)):

    • 任意修饰的com.xyz.service包的AccountService类的任意方法,任意返回值,任意的参数
  4. execution(* com.xyz.service..(…)):

    • 任意修饰的com.xyz.service包的任意类的任意方法,任意返回值,任意的参数
  5. execution(* com.xyz.service….(…)):

    • 任意修饰的com.xyz.service包(包括所有的子包)的任意类的任意方法,任意返回值,任意的参数
  • ProxyFactoryBean
    • ProxyFactoryBean是FactoryBean接口的实现类,FactoryBean负责实例化一个Bean,而ProxyFactoryBean负责为其他Bean创建代理实例。在Spring中,使用ProxyFactoryBean是创建AOP代理的基本方式。

在这里插入图片描述

  • 实现AOP
  • 基于XML实现
  1. 添加依赖
    在这里插入图片描述

  2. 创个接口(UserDao.java)
    在这里插入图片描述

  3. 创建一个实现类,UserDaorel02.java实现上面的接口
    在这里插入图片描述

  4. 配置文件application.xml
    在这里插入图片描述

  5. 创建一个实现AOP的类MyAspect类

在这里插入图片描述

  1. 创建一个测试类,测试一下这个接口和AOP是否成功
    在这里插入图片描述

结果测试成功。

  • 基于注解实现
  1. 添加依赖
  2. 编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 设置包扫描 -->
	<context:component-scan base-package="example04" />

	<!-- 设置开启AOP注解 -->
	<aop:aspectj-autoproxy />

</beans>
  1. 编写接口
public interface Service {

	public void save();

	public void delete();

	public void update();

	public int query();

	public void batch();

}
  1. 编写实现类,实现接口
@Service
public class UserDaorel02 implements UserDao {

	@Override
	public void save() {
		System.out.println("执行save");
	}

	@Override
	public void delete() {
		System.out.println("执行delete");
	}

	@Override
	public void update() {
		System.out.println("执行update");
	}

	@Override
	public int query() {
		System.out.println("执行query");
		return 100;
	}

	@Override
	public void batch() {
		System.out.println("执行batch");
	}
}
  1. 编写代理类
@Component
// 使用@Aspect表示这个类就是切面类
@Aspect
public class MyProxy {

	/**
	 * 定义前置通知
	 */
	@Before("execution(* save*(..))")
	public void saveMethodProxy() {
		System.out.println("执行之前进行权限校验");
	}

	/**
	 * 定义后置通知
	 */
	@AfterReturning(value = "execution(* query*(..))")
	public void afterMethodProxy() {
		System.out.println("我是后置通知");
	}

	/**
	 * 定义环绕通知
	 * 
	 * @throws Throwable
	 */
	@Around(value = "execution(* update*(..))")
	public void aroundMethodProxy(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("我是环绕通知,在之前执行");
		// 通过执行proceed方法才会执行我们目标类中的方法
		joinPoint.proceed();
		System.out.println("我是环绕通知,在之后执行");
	}

	/**
	 * 异常通知
	 * 
	 * @throws Throwable
	 */
	@AfterThrowing(value = "execution(* delete*(..))")
	public void exceptionMethodProxy(){
		System.out.println("我是异常通知,在出现异常的时候执行");
	}

	/**
	 * 最终通知
	 * 
	 * @throws Throwable
	 */
	@After(value = "execution(* batch*(..))")
	public void afterMethodProxy2() {
		System.out.println("我是最终通知,就算程序有异常,也会执行");
	}

}
  1. 最后写个测试方法测试一下
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext2.xml")
public class TestUserDao {

	@Autowired
	private PeopleService peopleService;

	@Test
	public void testSaveMethod() {
		this.peopleService.save();
		this.peopleService.query();
		this.peopleService.update();
		this.peopleService.delete();
		this.peopleService.batch();
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值