唯's Blog

笔者是一个热爱编程的 Java 程序员。

0%

Spring API

基于插口 BeanPostProcessor 实现的一些 Spring 高级特性

  • AnnotationAwareAspectJAutoProxyCreator -> AOP 接入 Spring 核心扩展点,带有 @Aspect 将在这里 InstantiationAwareBeanPostProcessor 生成代理对象
1
2
3
4
5
6
7
8
9

>AnnotationAwareAspectJAutoProxyCreator extends... AbstractAutoProxyCreator

>AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor

>SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor



InstanitiationAwareBeanPostProcessor 含有 6 个扩展点

  • postProcessBeforeInstantiation // 实例化之前
  • postProcessAfterInstantiation // 实例化之后
  • postProcessProperties // 依赖自动注入之前
  • postProcessPropertyValues // 依赖自动注入之后
  • postProcessBeforeInitialization // 初始化之前
  • postProcessAfterInitialization // 初始化之后

SmartInitializingSingleton (since spring 4.1)

  • afterSingletonsInstantiated // 在容器非LazySingleton都已被初始化完成后执行
  • AsyncAnnotationBeanPostProcessor (extends AdviceModeImportSelector)

    @Async -> @import -> AsyncConfigurationSelector -> ProxyAsyncConfiguration -> @Bean -> AsyncAnnotationBeanPostProcessor

  • ProxyTransactionManagementConfiguration (extends AdviceModeImportSelector) -> @Transcation

  • @Transcation 声明式事务依赖 AOP, 核心原理是通过 @EnableTransactionManagement-> import(TransactionManagementConfigurationSelector->)ProxyTransactionManagementConfiguration -> 注入声明式事务的advisor BeanFactoryTransactionAttributeSourceAdvisor -> 通过advisor aop 完成事务的添加 BeanFactoryTransactionAttributeSourceAdvisor

AOP

Spring AOP 的实现是通过动态代理。核心是添加一堆的advisor (切点+通知)(@Aspect 切面会被解析成List), 声明式事务 本质 添加一个 advisor

代码

spring中expose-proxy的作用与原理

先看一下几个问题,下面是段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

public interface UserService{

public void a();

public void a();

}



public class UserServiceImpl implements UserService{

@Transactional(propagation = Propagation.REQUIRED)

public void a(){

this.b();

}

@Transactional(propagation = Propagation.REQUIRED_NEW)

public void b(){

System.out.println("b has been called");

}

}

ps:代码参照《Spring源码解析》p173页。

Q1:b中的事务会不会生效?

A1:不会,a的事务会生效,b中不会有事务,因为a中调用b属于内部调用,没有通过代理,所以不会有事务产生。

Q2:如果想要b中有事务存在,要如何做?

A2:<aop:aspectj-autoproxy expose-proxy=“true”> ,设置expose-proxy属性为true,或者在@EnableAspectJAutoProxy(exposeProxy = true)` 将代理暴露出来,使用AopContext.currentProxy()获取当前代理,将this.b()改为((UserService)AopContext.currentProxy()).b()

还要一个方法:

使用cglib的方式,是可以实现代理的,会执行成功!这个也是和jdk默认的动态代理的不同点