Spring AOP源码解读

AOP 是什么

AOP (Aspect-Oriented Programming,面向切面编程),可以说是 OOP 的补充和完善。OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP 则显得无能为力。OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切代码

面向切面编程,核心原理是使用动态代理模式在方法执行前后或出现异常时加入相关逻辑

AOP 的使用场景

  • Authentication 权限的处理
  • Cache 缓存的处理
  • Transactions 事务的处理
  • Performance optimization 性能的优化等

AOP 相关概念

  • 切入点 Pointcut:指定一个通知将被引发的一系列连接点的集合。AOP 框架必须允许开发者指定切入点:例如,使用正则表达式。spring 定义了 Pointcut 接口,用来组合MethodMatcherClassFilter,可以通过名字很清楚的理解,MethodMatcher 是用来检查目标类的方法是否可以被应用此通知,而 ClassFilter 是用来检查 Pointcut 是否应该应用到目标类上
  • 连接点 Joinpoint:程序执行过程中明确的点,如方法的调用或特定的异常被抛出
  • 通知 Advice:在特定的连接点,AOP 框架执行的动作。各种类型的通知包括 around、beforethrows 通知。许多 AOP 框架包括 spring 都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。spring 中定义了四个 adviceBeforeAdvice, AfterAdvice, ThrowAdvice,DynamicIntroductionAdvice
  • 切面 Aspect:一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是 J2EE 应用中一个很好的横切关注点例子。方面用 springAdvisor 或拦截器实现
  • 织入 Weaving:组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ 编译器),也可以在运行时完成

Spring AOP 的简单实现

引入 maven 依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
</parent>	   
<dependency>      
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-aop</artifactId>  
</dependency> 

创建接口及其实现类

public interface Person {
   
	void say();
}

public class Student implements Person{
   
 
	public void say(){
   
		System.out.println("这是一个苦逼的程序员");
	}
}

创建切面类

@Aspect
public class AspectJTest {
   
 
	@Pointcut("execution(* *.say(..))")
	public void test(){
   }
	
	@Before("test()")
	public void before(){
   
		System.out.println("before test..");
	}
	
	@After("test()")
	public void after(){
   
		System.out.println("after test..");
	}
	
	@Around("test()")
	public Object around(ProceedingJoinPoint p){
   
		System.out.println("before1");
		Object o = null;
		try {
   
			o = p.proceed();
		} catch (Throwable e) {
   
			e.printStackTrace();
		}
		System.out.println("after1");
		return o;
	}
}

测试类

public class Test {
   
 
	public static void main(String[] args) {
   
 
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
		Person bean2 = (Person)ac.getBean("student");
		bean2.say();
	}
}

测试结果

	before1
    before test..
    这是一个苦逼的程序员
    after1
    after test..

Spring AOP 源码解读

读源码之前

  • 在使用 ApplicationContext 相关实现类加载 bean 的时候,会对所有单例且非懒加载的 bean在构造 ApplicationContext 的时候就会初始化好这些 bean,而不会等到使用的时候才去初始化。这也就是单例 bean 默认非懒加载的应用

  • 结合以上,被代理后的 bean,实际在 ApplicationContext 构造完成之后就已经被创建完成,getBean() 的操作直接从一级缓存 singletonObjects 中获取即可

beanPostProcessorbeanFactoryPostProcessor

  • beanPostProcessor 接口: bean 后置处理器。beanPostProcessor 能在 spring 容器实例化 bean 之后,bean 初始化前或后bean 做一些修改。而 aop 的功能实现正式基于此,在 bean 初始化后创建针对该 beanproxy,然后返回给用户该 proxy

  • beanFactoryPostProcessor 接口:beanFactoryPostProcessor 接口是针对 bean 容器的,它的实现类可以在当前 spring 容器加载 bean 定义后,bean 实例化之前修改 bean 的定义属性,达到影响之后实例化 bean 的效果

spring 中单例 bean 的初始化主要过程

  • createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
  • populateBean:填充属性,这一步主要是多 bean 的依赖属性进行填充
  • initializeBean:初始化,执行该 bean 的一些初始化方法

寻找 aop 注解对应的解析器

public class AopNamespaceHandler extends NamespaceHandlerSupport {
   

	@Override
	public void init() {
   
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser(
  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值