Spring学习笔记——AOP

一、Spring AOP

1、AOP简介
面向切面编程(AspectJ Oriented Programming,AOP)是对面向对象编程(OOP)的有益延伸和补充。AOP适用于具有横切逻辑的场合,如访问控制、事务管理、日志记录,异常处理,性能检测等。

AOP采取横向抽取机制,将分散在各个方法中的重复代码抽取出来,然后在程序编译或运行时,再将这些抽取出来的代码应用到需要执行的地方。AOP采用横向抽取机制的方式实现代码复用,而OOP只能实现父子关系的纵向的重用。

目前流行的两个AOP框架:Spring AOP和AspectJ。SpringAOP使用纯Java实现,不需要专门的编译器和类加载器,在运行时通过代理方法向目标类织入增强代码。
AspectJ是一个基于Java语言的AOP框架,提供了一个专门的编译器,在编译时提供横向代码的织入。

2、AOP术语
(1)Aspect(切面):指封装的用于横向插入系统功能(如事务,日志)的类。
(2)JoinPoint(连接点):指在程序执行过程中的某个阶段点,它实际上是对象的一个操作,如方法的调用或异常的抛出。在Spring AOP中,连接点指方法的调用。
(3)Pointcut(切入点):指切面与程序流程的交叉点,即那些需要处理的连接点。
(4)Advice(通知/增强处理):指AOP框架在特点切入点执行的代码
(5)Target Object(目标对象):指所有被通知的对象。如果AOP框架采用的是动态的AOP实现,那么该类就是一个被代理的对象。
(6)Proxy(代理):指将通知应用到目标对象之后,被动态创建的对象。
(7)AOP Proxy(AOP代理):指由AOP框架所创建的对象,实现执行增强处理方法等功能。
(8)Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程。

3、动态代理
AOP中的代理就是由AOP框架动态生成一个对象,该对象可以作为目标对象使用。通过代理对象中的代理方法调用原对象的方法时,可以在代理方法中添加新的功能,功能可以插在原方法之前或之后。
Spring学习笔记——AOP_第1张图片4、Spring AOP
SpringAOP的两种代理方式:JDK动态代理和CGLIB代理
(1)JDK动态代理:
JDK动态代理是通过java.lang.reflect.Proxy类实现的。对于使用业务接口的类,Spring框架默认使用JDK动态代理实现AOP。
JDK动态代理实现过程:
目标类:

public interface UserDao{
   
	public void addUser();
	public void delUser();
}
//目标类
@Repository("userDao")
public class UserDaoImpl implements UserDao{
   
	public void addUser(){
   
		//int i=10/0;
		System.out.println("添加用户");
	}
		public void delUser(){
   
		System.out.println("删除用户");
	}
}

切面类:

//切面类:可以存放多个Advice
public calss MyAspect{
   
	public void checkPermission(){
   
		System.out.println("模拟检查权限...");
	}
	public void log(){
   
		System.out.println("模拟日志记录...");
	}
}

代理类:需要实现InvocationHandler接口

//JDK代理类
public class JdkProxy implements InvocationHandler{
   
	//声明目标类接口
	private UserDao userDao;
	//创建代理类方法
	public Object createProxy(UserDao userDao){
   
			this.userDao=userDao;
			//1.类加载器
			ClassLoader classLoader=JdkProxy.calss.getClassLoader();
			//2.被代理对象实现的所有接口
			Class[] clazz=userDao.getClass().getInterfaces();
			//3.使用代理类进行增强,返回的是代理后的对象
			return Proxy.newProxyInstance(classLoader,clazz,this);
	}
	//所有动态代理类的方法调用,都会交由invoke()处理
	//proxy:被代理后的对象 method:将要被执行的方法信息(反射) args:执行方法时的参数
	@Override
	public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
   
		//声明切面
		MyAspect myAspect=new MyAspect();
		//前增强
		myAspect.checkPermission();
		//调用目标类上的方法,传入参数
		Object obj=method.invoke(userDao,args);
		//后置增强
		myAspect.log();
		return obj;
	}	
}

测试:

@Test
public void test(){
   
	//1.创建代理对象
	JdkProxy jdkProxy=new JdkProxy();
	//2.创建目标对象
	UserDao userDao=new UserDaoImpl();
	//3.获取增强后的对象
	UserDao userDao1=(UserDao)jdkProxy.createProxy(userDao);
	//4.执行方法
	userDao1.addUser();
	userDao1.delUser();
}

JDK动态代理的局限性:使用JDK动态代理时,目标类必须实现一个或多个接口。

(2)CGLIB
如果要对没有实现接口的类进行代理,那么可以使用CGLIB代理。CGLIB采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。
目标类:

//目标类
public class UserDao {
   
    public 

你可能感兴趣的:(SSM,Spring)