Spring学习笔记三(AOP使用)

  • 注:这是学习过程的一些个人笔记,可能理解不够,会有错误的地方。

AOP的简介

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,AOP的提出是为了解决面对对象编程的一些弊端,比如,在一个实际项目中,如果需要测试某一类业务的性能,最传统的方法就是把这些的业务的源代码找到,然后在这些代码中编写测试性能的代码,一个业务就要编写一个测试性能代码,有多少业务就要写多少个,最后测试好了,我们还需要把这些测试代码从源代码中删除,这是特别麻烦的一件事,为了解决这么高的代码耦合度,我们可以使用动态代理模式来对一些业务进行一些增强,动态代理模式就可以让我们在不修改源代码的前提下对业务进行增强,AOP思想就是一种基于动态代理的思想,AOP思想就是将一些共性重复的代码抽取成一个独立模块,然后可以通过预编译方式,在运行期动态地将这些模块插入到需要的地方(方法)中,实现在不修改源代码的情况下给程序动态统一添加功能,从而大大降低了代码的耦合度。

AOP的专业术语

在使用AOP之前需要了解AOP的专业术语
target:目标类,即一个类中有方法要被用来增强,例如UserDaoImpl的save方法要增强,这个类就是目标类
joinPoint:连接点,即可以被用来增强的方法,例如UserDaoImpl的增删改查方法都可以被用来增强
pointCut:切入点,即要被增强的方法,就是说save要被增强,就是切入点,注意与可以增强区别
Proxy:代理,即被增强方法后的代理对象
advice:通知,添加进去的一段增强代码或者方法,也就是在原本的方法加入的一段增强的代码
weaving:织入,即将增强代码加入被增强方法的一个过程
aspect:切面,即被增强的方法+增强的方法,pointCut+advice

AOP的通知类型

前置通知:方法执行前增强
后置通知:方法执行后增强
环绕通知:方法执行前后增强
异常通知:方法抛出异常时增强
最终通知:方法无论是否抛出异常都增强

使用AOP需要的包

要使用AOP除了Spring需要的6个基本包,还需要四个包,因为我们要使用的是spring基于Aspectj的aop,因此不仅需要aop的jar包,还需要关于aspect的包。
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar

AOP使用示例-XML方式

  • 目标类
package com.wzm.entity;
/*
 * 用来被增强的目标类
 */
public class UserDaoImpl {
	
	public void save() {
		System.out.println("普通保存");
	}
	public String delete() {
		System.out.println("普通删除");
		//这里返回一个值用来测试后置通知
		return "小明";
	}
	public void update() {
		System.out.println("普通更新");
	}
	public void find() {
		System.out.println("普通查询");
		//这里抛出一个异常用来测试异常通知
		int i = 1 / 0;
	}
}

  • 切面类
package com.wzm.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

/*
 * 通知类
 */
public class MyAspect {
	
	//前置通知
	public void before() {
		System.out.println("前置通知");
	}
	
	//后置通知,参数为原本方法的返回值
	public void afterReturning(Object result) {
		System.out.println("后置通知通知=="+result);
	}
	
	//环绕通知,参数为一个连接点,相当于原本方法
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("环绕前通知");
		//在环绕通知中间,执行以下原本的方法,获得返回值
		Object obj = joinPoint.proceed();
		System.out.println("环绕前通知");
		return obj;
	}
	
	//异常通知,参数为原本方法抛出的异常对象
	public void afterThrowing(Throwable e) {
		System.out.println("异常通知==="+e.getMessage());
	}
	
	//最终通知
	public void after() {
		System.out.println("最终通知");
	}
}

  • 配置文件



        
        
        
        
         
        
        
        
        
        
        
        	
        	
        	
        	
        	
        	
        	
        	
        		
        		
        		
        		
        		
        		
        		
        		
        		
        		
        	
        

AOP使用示例-注解方式

  • 目标类
package com.wzm.entity;

import org.springframework.stereotype.Repository;

/*
 * 用来被增强的目标类--使用注解的方式
 */
@Repository("userDao")
public class UserDaoImpl {
	
	public void save() {
		System.out.println("普通保存");
	}
	public String delete() {
		System.out.println("普通删除");
		//这里返回一个值用来测试后置通知
		return "小明";
	}
	public void update() {
		System.out.println("普通更新");
	}
	public void find() {
		System.out.println("普通查询");
		//这里抛出一个异常用来测试异常通知
		int i = 1 / 0;
	}
}

  • 切面类
package com.wzm.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/*
 * 通知类 -- 注解方式
 * @Aspect表明该类是一个通知类
 */
@Aspect()
@Component("myAspect")
public class MyAspect {
	
	//前置通知
	@Before(value="execution(* com.wzm.entity.UserDaoImpl.save(..))")
	public void before() {
		System.out.println("前置通知");
	}
	
	//后置通知,参数为原本方法的返回值
	@AfterReturning(value="execution(* *.*.*.UserDaoImpl.delete(..))",returning="result")
	public void afterReturning(Object result) {
		System.out.println("后置通知通知=="+result);
	}
	
	//环绕通知,参数为一个连接点,相当于原本方法
	@Around(value="execution(* *.*.*.UserDaoImpl.update(..))")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("环绕前通知");
		//在环绕通知中间,执行以下原本的方法,获得返回值
		Object obj = joinPoint.proceed();
		System.out.println("环绕前通知");
		return obj;
	}
	
	//异常通知,参数为原本方法抛出的异常对象
	@AfterThrowing(value="execution(* *.*.*.UserDaoImpl.find(..))",throwing="e")
	public void afterThrowing(Throwable e) {
		System.out.println("异常通知==="+e.getMessage());
	}
	
	//最终通知
	@After(value="execution(* *.*.*.UserDaoImpl.find(..))")
	public void after() {
		System.out.println("最终通知");
	}
}

  • 配置文件



        
       
        
        
        
        
        
      

  • 测试类
package com.wzm.test;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.wzm.entity.UserDaoImpl;

//使用整合Junit的测试方式
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value="classpath:applicationContext.xml")
public class AspectTest {
	
	//通过注解获取要被增强的对象
	@Resource(name="userDao")
	private UserDaoImpl userDao;
	
	@Test
	public void test1() {
		userDao.save();
	}
	@Test
	public void test2() {
		userDao.delete();
	}
	@Test
	public void test3() {
		userDao.update();
	}
	@Test
	public void test4() {
		userDao.find();
	}
}

你可能感兴趣的:(Spring框架学习笔记)