我们都知道 Spring 的事务管理有两种方式,编程性事务和声明式事务,而声明式事务是基于 aop 来实现的,上篇文章分析了 Spring Bean 的一个初始化过程,本文来聊聊 Spring aop 的源码执行过程。
为简单起见,这里就不搞那么复杂的分层了,本项目的目的是利用 spring aop 来计算一个方法的执行时间
@EnableAspectJAutoProxy
@ComponentScan("com.lhg.demo.*")
public class App{
public static void main( String[] args ) throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(App.class);
//本意是输出 user 对象
User user = (User) ac.getBean("user");
user.compute();
}
}
@Component
public class User {
//计算 0-800000000 耗时操作
public void compute() throws Exception{
ForkJoinPool pool = new ForkJoinPool();
MyTask task = new MyTask(0, 800000000);
Future<Long> future = pool.submit(task);
System.out.println("多线程加法: " + future.get());
pool.shutdown();
}
public User() {
System.out.println("User constructor....");
}
}
@Aspect
@Component
public class MyAspect {
//指定切入点表达式
@Pointcut("execution(* com.lhg.demo.config.*.*())")
public void pointCut(){}
/**
* spring 框架为我们提供了一个接口:ProceedingJoinPoint,该接口有一个方法proceed(),
* 此方法就相当于明确调用切入点方法,该接口可以作为环绕通知的方法参数,在程序执行时,
* spring 框架会提供该接口的实现类供我们使用
**/
@Around("pointCut()")
public Object aroundPringLog(ProceedingJoinPoint pjp){
try {
Object res ;
Object[] args = pjp.getArgs();//这个参数就是实际方法执行所需的参数
long start = System.currentTimeMillis();
res = pjp.proceed(args);//明确调用业务层方法(切入点方法)
long end = System.currentTimeMillis();
System.out.println("总时间:"+(end-start));
return res;
}catch (Throwable t){//这个异常必须写Throwable,Exception拦不住的
throw new RuntimeException(t);
} finally {
}
}
}
/*
* 来复习下 分支合并线程池
*/
public class MyTask extends RecursiveTask<Long> {
final static int MAX_SIZE = 500;//定义切割的步长值
int begin, end;
public MyTask(int begin, int end) {
this.begin = begin;
this.end = end;
}
protected Long compute() {
if ((end - begin) <= MAX_SIZE) {//如果比步长值小直接累加就好
long sum = 0L;
for (int i = begin; i <= end; i++) {
sum += i;
}
return sum;
} else {//否则开启任务分治递归相加再汇总
int middle = begin + (end - begin) / 2;
MyTask task1 = new MyTask(begin, middle);
MyTask task2 = new MyTask(middle + 1, end);
task1.fork();// 就是用于开启新的任务的。 就是分支工作的。 就是开启一个新的线程任务。
task2.fork();
// join - 合并。将任务的结果获取。 这是一个阻塞方法。一定会得到结果数据。
return task1.join() + task2.join();
}
}
}
这个小案例的目的是测试 User 类中的 test 方法耗时,为了不修改原有业务,我们使用 AOP ,从这里可以看出 AOP 的一大特点,简单的说就是把程序重复的代码抽取出来,在需要执行的时候,使用动态代理技术,在不修改源码的基础上对原有方法进行增强。
运行项目,查看结果
D:\ProgramFiles\Java\jdk1.8.0_201\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=52765:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath 3.6.0\localRepository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar com.lhg.demo.spring.App
User constructor....
多线程加法: 320000000400000000
总时间:655
Process finished with exit code 0
经过 debug 发现,Spring bean 初始化过程中就已经完成了代理,
对程序 debug 你会发现 user 是个代理类,那问题来了,究竟是什么时候生成的呢,是在 getBean 的时候还是初始化的时候?
MyAspect 类的方法是如何被调用的?
在上篇文章分析的时候说过,在Spring bean 初始化过程中有一个 refresh() 方法非常重要,而且其中invokeBeanFactoryPostProcessors
finishBeanFactoryInitialization
两个方法非常重要
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
...
try {
this.postProcessBeanFactory(beanFactory);
//设置执行自定义的 ProcessBeanFactory 和 Spring 内部定义的的
this.invokeBeanFactoryPostProcessors(beanFactory);
...
//实例化对象
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} ...
}
}
根据之前文章的分析,bean的实例化是在 finishBeanFactoryInitialization() 方法进行操作的,大致过程如下
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
....
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
}
进入 preInstantiateSingletons() 方法,层层查看,最终找到 doGetBean() 方法,因为 Spring的源码太过庞大,所以查看源码的时候就要有的放矢,比如我们这次要 查看 bean 的实例初始化过程,那么在看源码时那些没有返回值的可以略过,有返回值但返回值类型是基本类型或者 String 可以不看,然后按照 Spring 的编码规范,方法见名知意,再通过 debug,条件断点,就能大致判断是哪个方法了
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("...");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
。。。
}
} 。。。
}
还记得吧,对象的创建是在 createBean 方法中,经过获得 class、推断构造方法、并反射,实例化对象,然后把创建好的 bean 返回出来
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-proce ssors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//得到 class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
...
try {
//在 doCreateBean 方法中创建对象
//推断构造方法,并反射,实例化对象
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//在这个方法里面完成了对象的创建
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
// Allow post-processors to modify the merged bean definition.
//从 java-doc 可以看出这里说的是可以通过 post-processors 去 modify 合并的 beandefinition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
...
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//从 java-doc 可以看出这里是 缓存对象来解决循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
...
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//完成属性填充
//比如 A类里面有个 B,那么这个方法就是完成 B 的注入
populateBean(beanName, mbd, instanceWrapper);
//主要执行各种生命周期回调方法以及 AOP 等
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
...
}
595 行没有执行完前,user 对象已经被放入 singletonObjects 单例池了,而且这个时候没有完成代理
当继续往下执行时,可以看到已经完成了代理
所以去看看方法底层实现
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
...
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
//直接进去看源码
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//发现经过这一步创建了代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
...
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//查看 getProxy() 方法的源码
return proxyFactory.getProxy(this.getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
//到这里已经很明显了,createAopProxy() 创建了代理对象,而 getProxy()可以看到动态代理的底层实现(字节码实现)
return this.createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
//使用 jdk 动态代理,基于接口的动态代理
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
//使用 cglib 动态代理,基于子类的动态代理
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
对 if 条件进行分析,isOptimize 和 isProxyTargetClass 是属性,isProxyTargetClass 可以在@EnableAspectJAutoProxy 注解进行赋值,而 hasNoUserSuppliedProxyInterfaces 方法便是判断类是否有继承自接口,由于 User 并没有实现某接口,所以会 走 cglib,通过 debug 也可以证实
好,为了更好验证动态代理,现在让 User 类 实现一个接口,debug 看看是否会走 JKD动态代理
@Component
public class User implements ComputerMapper {
//计算 0-800000000 耗时操作
@Override
public void compute() throws ExecutionException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
MyTask task = new MyTask(0, 800000000);
Future<Long> future = pool.submit(task);
System.out.println("多线程加法: " + future.get());
pool.shutdown();
}
public User() {
System.out.println("User constructor....");
}
}