- AOP是什么?
- AOP的相关名词
- 切面
- 切入点
- 通知
- 切面
- 目标
- 代理
- StringAOP的实现
- 代理
- jdk代理
- JDK代理的优缺点
- cglib代理
AOP是Spring两大特性之一,他的意思为面向切面编程。使用AOP可以抽取一些公共模块出来,减少公共模块和业务代码的耦合。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各 部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 AOP、OOP 在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP (面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获 得更加清晰高效的逻辑单元划分。
类中可以被增强的方法,这个方法就被称为连接点
切入点类中有很多方法可以被增强,但实际中只有 add 和 update被增了,那么 add 和 update 方法就被称为切入点(实际实现的连接点)
通知通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知、异常通知和返回通知等.
切面把通知添加到切入点的过程叫切面.
目标代理的目标对象(要增强的类)
代理向目标对象应用通知之后创建的代理对象
StringAOP的实现具体实现方式翻阅之前写的博客
AOP和事务管理
SpringAOP是通过代理来实现面向切面编程的,它使用的代理有两种,JDK代理和CGlib代理。当我们的bean对象实现了某一接口后,Spring默认将采用Jdk动态代理,当我们的bean对象没有实现接口时,默认将采用CGLIB代理,Spring也支持我们在bean对象实现了接口时也强制的使用CGLIB代理。
jdk代理JDK动态代理基于拦截器和反射来实现。代理类必须要实现InvocationHandler接口,重写invoke()方法。
代码实现:
接口类:UserDao
//抽象用户操作定义
public interface UserDao {
void saveUser();
}
两个实现类,普通用户实现UserDaoImpl和VIP用户实现VipUserDaoImpl
public class UserDaoImpl implements UserDao{
@Override
public void saveUser() {
System.out.println("普通用户实现");
//增加新功能要在每个实现类里面写
//saveLog()
}
}
public class VipUserDaoImpl implements UserDao{
@Override
public void saveUser() {
System.out.println("VIP用户实现");
//增加新功能要在每个实现类里面写
//saveLog()
}
}
动态代理类Dtproxy
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//实现java.lang包下的reflect类的InvocationHandler接口
public class Dtproxy implements InvocationHandler {
Object object;//真实对象
public Dtproxy(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("之前开始事务");
method.invoke(object);
System.out.println("之后提交事务");
return proxy;
}
}
测试类Test:
public class Test {
public static void main(String[] args) {
VipUserDaoImpl vipUserDao = new VipUserDaoImpl();
InvocationHandler dtproxy = new Dtproxy(vipUserDao);
//创建代理对象
UserDao userDao = (UserDao)Proxy.newProxyInstance(Dtproxy.class.getClassLoader(),VipUserDaoImpl.class.getInterfaces(),dtproxy);
userDao.saveUser();
}
}
JDK代理的优缺点
JDK代理是通过反射来实现,JDK通过反射,生成一个代理类,这个代理类实现了原来那个类的所有接口,并对接口定义的方法进行代理。当我们通过代理对象执行原来那个类的方法时,代理类底层会通过反射机制,回调我们实现的InvocationHandler接口的invoke方法。
优点:
- JDK动态代理是JDK原生的,不需要任何依赖即可使用;
- 通过反射机制生成代理类的速度要比CGLib操作字节码生成代理类的速度更快;
缺点:
- 如果要使用JDK动态代理,被代理的类必须实现了接口,否则无法代理;
- JDK代理必须要有实现类实现目标接口。
- JDK动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低;
CGLIB实现动态代理的原理是:底层采用ASM字节码生成框架,直接对需要代理的类的字节码进行操作,生成这个类的一个子类,并且重写类的所有方法。
优点:
- 使用CGLib代理的类,不需要实现接口,因为CGLib生成的代理类是直接继承自需要被代理的类;
- CGLib生成的代理类是原来那个类的子类,这就意味着这个代理类可以为原来那个类中,所有能够被子类重写的方法进行代理;
- CGLib生成的代理类,和我们自己编写并编译的类没有太大区别,对方法的调用和直接调用普通类的方式一致,所以CGLib执行代理方法的效率要高于JDK的动态代理;
缺点
- 由于CGLib的代理类使用的是继承,这也就意味着如果需要被代理的类是一个final类,则无法使用CGLib代理
- 由于CGLib实现代理方法的方式是重写父类的方法,所以无法对final方法,或者private方法进行代理,因为子类无法重写这些方法;
- CGLib生成代理类的方式是通过操作字节码,这种方式生成代理类的速度要比JDK通过反射生成代理类的速度更慢;



