文章目录

  • 什么是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动态代理后置通知......