首先AOP跟OOP(面向对象编程)、IOC(控制反转)一样都是一种编程思想
跟OOP不同, AOP是面向切面编程, 面对多个不具备继承关系的对象同时需要引入一段公共逻辑的时候, OOP就显得有点笨重了, 而AOP就游刃有余, 一个切面可以横跨多个类或者对象去执行公共逻辑, 极大的提升了开发效率
1、Spring AOP的关键概念
aspect: 切面 由切入点和通知共同组成, 执行一批对象抽象出来的公共逻辑, 比如事务切面、日志切面
pointCut: 切入点 拦截条件,符合条件的目标(类或者方法等)就会被拦截
advice: 通知 公共的增强逻辑
target: 目标对象 要代理的原始对象
joinPoint: 连接点 就是增强逻辑要执行的时机, 即被拦截下来的目标前或者后等
weaving: 织入 就是将切面和切面内的对象连接, 并执行代理增强的过程(分为静态织入和动态织入)
个人认为只要能清晰的理解切入点和连接点基本就能够在业务代码中很好的使用切面了
实际开发中我们会自己定义一个注解, 然后写一个handler去处理这个注解的逻辑
下面给大家提供一个demo, 体验一下
// 1 先定义一个注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopAdvise {
}
// 2 开发handler处理这个注解的逻辑
@Aspect
@Component
public class LoggingAspect {
@Pointcut("@annotation(com.demo.aop.ann.AopAdvise)")
public void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
AopAdvise ann = method.getAnnotation(AopAdvise.class);
System.out.println(ann);
System.out.println("增强方法之前");
}
}
// 3 在业务中使用
@Service("a")
public class A implements Obj {
@Override
@AopAdvise
public void p() {
System.out.println("a");
}
}
2、Spring是通过动态代理的方式实现AOP增强的, 具体过程如下
在Spring的Bean生周期管理过程中实现了AOP的思想, 具体是在Bean初始化的时候initializeBean方法中执行了applyBeanPostProcessorsAfterInitialization方法
public Object applyBeanPostProcessorsAfterInitialization(...)throws BeansException {
Object result = existingBean;
//循环遍历所有的BeanPostProcessor执行postProcessAfterInitialization方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
主要是在AbstractAutoProxyCreator类中实现, 继续追踪代码
public abstract class AbstractAutoProxyCreator... {
public Object postProcessAfterInitialization(...) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyBeanReferences.remove(cacheKey) != bean) {
//在这个方法中创建了代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理对象
Object proxy = createProxy(...);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
...
}
}
//一直追踪代码你会看到下面的结果
public AopProxy createAopProxy(...) throws AopConfigException {
if (...) {
//cglib代理
return new ObjenesisCglibAopProxy(config);
} else {
//jdk代理
return new JdkDynamicAopProxy(config);
}
}
至此可以确定 Spring就是通过动态代理的方式实现AOP增强, 方式有两种, jdk基于接口做代理, cglib基于字节码技术(ASM代码生成库)做代理