代理模式
AOP 的原理其实就是一种代理模式,那么什么是代理模式呢?比如公司有一个JavaProgramer, 一个 Manager
公司要通过 Manager 去驱动 JavaProgramer 干活。这个就是 Manager 代理 JavaProgramer ,代理模式
见下面代码:
// JavaProgramerpackage com.example.others;public class JavaProgramer {public void work(){System.out.println("JavaProgramer: Write Java code");}}//Manager.javapublic class Manager extends JavaProgramer{private JavaProgramer javaProgramer;public Manager(JavaProgramer javaProgramer) {this.javaProgramer = javaProgramer;}@Overridepublic void work() {System.out.println("Manager: Go to work! ");javaProgramer.work();}}
然后执行
package com.example.others;public class MainFunc {public static void main(String[] args) {JavaProgramer javaProgramer = new JavaProgramer();Manager m = new Manager(javaProgramer);m.work();}}
这就是代理模式
AOP 实现和原理
既然 AOP 原理是一种代理模式,那是怎么实现的呢? 我们可以写一下代码,来了解其实现过程
引入依赖
引入spring 对 AOP 的支持
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency>
编写切面代码
假设存在一个 CheckAspect 类
package com.example.code.aspect;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Aspect@Componentpublic class CheckAspect {// 在执行 UserService 每个方法前执行@Before("execution(public * com.example.code.services.UserService.*(..))")public void init(){System.out.println("init checking...");}}
然后就直接在 Main 里面enable
...@EnableAspectJAutoProxypublic class Main {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);UserService userService = context.getBean(UserService.class);User user = userService.Register();}}
最后执行会得到输出
init checking...Register Userregister successful
原理
其实背后的原理就是代理。 当我们做如上的配置的时候, Spring 在后面帮我们实现了一个代理类
public UserServiceAopProxy extends UserService {private UserService target;private CheckAspect aspect;public UserServiceAopProxy(UserService target, CheckAspect aspect) {this.target = target;this.aspect = aspect;}public User register(String email, String password, String name) {aspect.init();return target.register(email, password, name);}}
这个类是 spring 自动帮我们在后台生成的,不需要我们自己编写。 而且真正执行的其实是这个类。
需要注意的是,这个切面要跟主代码文件位于同一个包下面。

