AOP - 图1

代理模式

AOP 的原理其实就是一种代理模式,那么什么是代理模式呢?比如公司有一个JavaProgramer, 一个 Manager
公司要通过 Manager 去驱动 JavaProgramer 干活。这个就是 Manager 代理 JavaProgramer ,代理模式
见下面代码:

  1. // JavaProgramer
  2. package com.example.others;
  3. public class JavaProgramer {
  4. public void work(){
  5. System.out.println("JavaProgramer: Write Java code");
  6. }
  7. }
  8. //Manager.java
  9. public class Manager extends JavaProgramer{
  10. private JavaProgramer javaProgramer;
  11. public Manager(JavaProgramer javaProgramer) {
  12. this.javaProgramer = javaProgramer;
  13. }
  14. @Override
  15. public void work() {
  16. System.out.println("Manager: Go to work! ");
  17. javaProgramer.work();
  18. }
  19. }

然后执行

  1. package com.example.others;
  2. public class MainFunc {
  3. public static void main(String[] args) {
  4. JavaProgramer javaProgramer = new JavaProgramer();
  5. Manager m = new Manager(javaProgramer);
  6. m.work();
  7. }
  8. }

这就是代理模式

AOP 实现和原理

既然 AOP 原理是一种代理模式,那是怎么实现的呢? 我们可以写一下代码,来了解其实现过程

引入依赖

引入spring 对 AOP 的支持

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-aspects</artifactId>
  4. <version>${spring.version}</version>
  5. </dependency>

编写切面代码

假设存在一个 CheckAspect 类

  1. package com.example.code.aspect;
  2. import org.aspectj.lang.annotation.Aspect;
  3. import org.aspectj.lang.annotation.Before;
  4. import org.springframework.stereotype.Component;
  5. @Aspect
  6. @Component
  7. public class CheckAspect {
  8. // 在执行 UserService 每个方法前执行
  9. @Before("execution(public * com.example.code.services.UserService.*(..))")
  10. public void init(){
  11. System.out.println("init checking...");
  12. }
  13. }

然后就直接在 Main 里面enable

  1. ...
  2. @EnableAspectJAutoProxy
  3. public class Main {
  4. public static void main(String[] args) {
  5. ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
  6. UserService userService = context.getBean(UserService.class);
  7. User user = userService.Register();
  8. }
  9. }

最后执行会得到输出

  1. init checking...
  2. Register User
  3. register successful

这里我们就成功实现了一个 AOP 切面

原理

其实背后的原理就是代理。 当我们做如上的配置的时候, Spring 在后面帮我们实现了一个代理类

  1. public UserServiceAopProxy extends UserService {
  2. private UserService target;
  3. private CheckAspect aspect;
  4. public UserServiceAopProxy(UserService target, CheckAspect aspect) {
  5. this.target = target;
  6. this.aspect = aspect;
  7. }
  8. public User register(String email, String password, String name) {
  9. aspect.init();
  10. return target.register(email, password, name);
  11. }
  12. }

这个类是 spring 自动帮我们在后台生成的,不需要我们自己编写。 而且真正执行的其实是这个类。

需要注意的是,这个切面要跟主代码文件位于同一个包下面。