Spring ——源码解析

63 阅读3分钟

SpringAOP 作为 Spring 最核心的能力之一,其重要性不言而喻。然后需要知道的是 AOP 并不只是 Spring 特有的功能,而是一种思想,一种通用的功能。而 SpringAOP 只是在 AOP 的基础上将能力集成到 SpringIOC 中,使其作为 bean 的一种,从而我们能够很方便的进行使用。

首先,先看下spring整体的一个流程。主要流程就是(1 读取类信息 2 初始化类) 这个过程中会涉及到很多的spring 框架的核心类

(1)BeanFactory,bean工厂 用来存放类的各种信息(beanDefination和实例化后的类)

(2)FactoryBean 一个工厂类,可以自己指定一个bean创建的过程

(3)Environment 承载着spring 上下文的一些信息

(4)BeanFactoryPostProcessor 作用在类实例化之前, 对beanDefination进行渲染修饰

(5)BeanPostProcessor 作用在类实例化之后,对类进行属性填充等

(6)AbstractApplicationContext 一个可以获取spring 框架上下文信息的类 之后源码学习就会一步步分析到这些类的具体作用

SpringAOP 的使用方式

1.1 使用场景

当我们在日常业务开发中,例如有些功能模块是通用的(日志、权限等),或者我们需要在某些功能前后去做一些增强,例如在某些方法执行后发送一条 mq 消息等。

如果我们将这些通用模块代码与业务代码放在一块,那么每个业务代码都要写这些通用模块,维护成本与耦合情况都十分严重。

因此,我们可以将此模块抽象出来,就有了” 切面 “的概念

1.2 常用方式

AOP 的使用方式相对比较简单,首先我们需要完成业务代码

@Service
public class AopDemo implements AopInterface{

    public Student start(String name) {
        System.out.println("执行业务逻辑代码.....");
        return new Student(name);
    }

}

综上我们可以总结如下的Bean的生命周期:
ApplicationContext的构造方法里面,开始扫@Component注解的类。

图片.png

Spring事务底层原理

事务开启会做两件事,一件是Spring自己建立一个JDBC连接,然后就是关闭自动提交。如果将提交和连接交给jdbcTemplate,那么就会出现jdbctemplate执行一个sql就提交一个,遇到异常抛出时,sql都已经提交了,回滚不回来了。所以需要spring自己管理一个连接。
spring事务失效的原理

@Transactional
public void test(){
    jdbcTemplate.execute("insert into t1 values(1,1,1)");
    a();
}
@Transactional
public void a(){
    jdbcTemplate.execute("insert into t1 values(2,2,2)");
}

JDK 代理

首先在获取代理对象时选择 JdkDynamicAopProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
   //这里通过反射创建代理对象
   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

当被代理对象执行被代理的方法时,会进入到此方法。(jdk 动态代理的概念)

JDK 通过反射创建对象,效率上来说相对低一些。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		try {
			// 获取被代理对象的所有切入点
			List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果调用链路为空说明没有需要执行的切入点,直接执行对应的方法即可
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 如果有切入点的话则按照切入点顺序开始执行
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}
			
			return retVal;
		}
}