文章目录
- 什么是AOP?
- Spring AOP
- JDK动态代理
- Cglib动态代理
什么是AOP?
AOP(Aspect Oriented Programming),面向切面编程,AOP不是单独指某一种技术,而是一种编程思想,AOP是OOP的一种补充,用于处理各个业务逻辑中的横切关注点,比如日志记录,事务处理,性能统计,异常处理等等。
AOP的主要功能是将大量的通用行为从业务逻辑中抽取出来,将这些行为封装成独立的非业务方法,用于横向切入,这些行为不会对已有的业务逻辑产生任何影响。
AOP是一种设计思想,而Spring AOP则是符合AOP思想的一种框架实现。
Spring AOP
Spring AOP主要有两种实现,分别的JDK动态代理和Cglib动态代理。
JDK动态代理
JDK动态代理是JDK内置的一种动态代理模式,使用反射来接受被代理的类,但是被代理的类必须实现一个接口。
Cglib动态代理
Cglib是一个代码生成的类库,可以在运行时动态生成某个类的子类,所以如果需要被Cglib动态代理,那么就需要被代理类不能被final修饰。
- 在Spring AOP中,如果一个类实现了接口,那么就使用JDK动态代理的方式进行AOP实现,而如果这个类没有实现接口,则使用Cglib动态代理的方式进行AOP实现。如果一个类既没有接口,同时又被final修饰,那么这个类不能进行AOP动态代理。
JDK动态代理
JDK动态代理,由于是JDK内置的代理模式,所以我们不需要引入任何依赖,可以直接使用。
1、编写JDK动态代理代码
public class JDKProxy implements InvocationHandler {
private Object target;
public JDKProxy(Object target){
this.target = target;
}
public Object createProxy() {
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理前置通知......");
Object object = method.invoke(target, args);
System.out.println("JDK动态代理后置通知......");
return object;
}
}
2、编写一个接口
public interface UserDao {
void save();
void update();
void find();
void delete();
}
3、编写被代理类实现该接口。
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("保存用户......");
}
@Override
public void update() {
System.out.println("修改用户......");
}
@Override
public void find() {
System.out.println("查找用户......");
}
@Override
public void delete() {
System.out.println("删除用户......");
}
}
4、测试
public class JDKProxyTest {
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
UserDao proxy = (UserDao) new JDKProxy(userDao).createProxy();
proxy.save();
proxy.update();
proxy.find();
proxy.delete();
}
}
5、测试结果
JDK动态代理前置通知......
保存用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
修改用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
查找用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
删除用户......
JDK动态代理后置通知......
Cglib动态代理
Cglib动态代理,需要引入外部依赖,我们可以直接引入Spring的核心依赖即可,Spring中有Cglib的类库。
1、引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
</dependencies>
2、编写Cglib动态代理代码
public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target){
this.target = target;
}
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
Object proxy = enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib动态代理前置通知......");
Object object = method.invoke(target, args);
System.out.println("Cglib动态代理后置通知......");
return object;
}
}
3、编写被代理类
public class CustomerDao {
public void save() {
System.out.println("保存客户......");
}
public void update() {
System.out.println("修改客户......");
}
public void find() {
System.out.println("查找客户......");
}
public void delete() {
System.out.println("删除客户......");
}
}
4、测试
public class CglibProxyTest {
public static void main(String[] args) {
CustomerDao customerDao = new CustomerDao();
CustomerDao proxy = (CustomerDao) new CglibProxy(customerDao).createProxy();
proxy.save();
proxy.update();
proxy.find();
proxy.delete();
}
}
5、测试结果
Cglib动态代理前置通知......
保存客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
修改客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
查找客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
删除客户......
Cglib动态代理后置通知......