为什么在我使用 EnableTransactionManagement(mode=Advice.ASPECTJ) 时 spring 事务不起作用?
Why spring transactions dont work when i use EnableTransactionManegment(mode=Advice.ASPECTJ)?
我尝试使用 Spring 事务和 AspectJ
**我的项目:
build.config
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id "io.freefair.aspectj.post-compile-weaving" version "5.1.0"
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
project.ext {
aspectjVersion = "1.8.2"
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework:spring-jdbc'
implementation 'org.springframework:spring-tx'
implementation 'org.postgresql:postgresql'
implementation 'org.aspectj:aspectjrt'
implementation 'org.aspectj:aspectjweaver'
implementation 'org.aspectj:aspectjtools'
implementation 'org.springframework:spring-aspects:5.3.2'
implementation 'org.springframework:spring-instrument:5.3.2'
}
test {
useJUnitPlatform()
}
DataConfig.class
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
public class DataConfig {
@Bean
public DataSource postgres() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres?serverTimezone=UTC");
dataSource.setUsername("postgres");
dataSource.setPassword("admin");
dataSource.setSchema("public");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(postgres());
}
}
MainDAO.class
@Repository
public class MainDAO {
private final JdbcTemplate jdbcTemplate;
public MainDAO(DataSource postgres) {
this.jdbcTemplate = new JdbcTemplate(postgres);
}
public Integer getSoundsCount() {
return jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM Sound", Integer.class);
}
@Transactional(propagation = Propagation.MANDATORY)
public void insertSound() {
insertAuthor();
jdbcTemplate.update(
"INSERT INTO Sound (author, name, id) VALUES (?,?,?)",
0, "Spring", 0);
}
}
当我从我的服务中调用方法 insertSound 时,它 运行 无一例外。 但它应该抛出异常,因为 insertSound 方法有 propogation.MANDATORY.
如果我将 EnableTransactionManegment 的 Advice 模式更改为 mode=Advice.PROXY 然后我得到异常
但是模式=Advice.ASPECTJ,事务不工作。
我也尝试使用带有注释 EnableLoadTimeWeaving 的 运行 应用程序并将库 spring-instrument 设置为 java 代理,但它也无法处理事务:
我应该怎么做才能使交易与模式一起工作=Advice.ASPECTJ?
加载时编织 (LTW)
为了使它与 LTW 一起工作,您可以在命令行上结合使用 -javaagent:path/to/aspectjweaver.jar
和 -javaagent:path/to/spring-instrument.jar
,并将您之前提到的 @EnableLoadTimeWeaving
添加到您的配置中。
编译时编织 (CTW)
我找到了使 Spring 的本机 AspectJ 声明性事务与编译时编织一起工作的方法,请参阅我的 pull request。其他细节中的一个关键是:
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(h2());
// Make native AspectJ declarative transactions work with compile-time weaving
AnnotationTransactionAspect.aspectOf().setTransactionManager(transactionManager);
return transactionManager;
}
另请参阅 以供参考。
当 运行 应用程序正常时(即没有任何 -javaagent
参数,因为事务方面已经被编译)在 mvn compile
之后,控制台日志应该显示 Native AspectJ active = true
每次调用 URI sounds/add
时。该日志行由我为说明添加的调试语句触发:
@Transactional//(propagation = Propagation.MANDATORY)
public void insertSound() {
boolean nativeAspectjActive = Arrays
.stream(new Exception().getStackTrace())
.map(StackTraceElement::toString)
.anyMatch(signature -> signature.contains("MainDAO.insertSound_aroundBody"));
logger.info("Native AspectJ active = " + nativeAspectjActive);
// (...)
}
我尝试使用 Spring 事务和 AspectJ
**我的项目: build.config
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id "io.freefair.aspectj.post-compile-weaving" version "5.1.0"
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
project.ext {
aspectjVersion = "1.8.2"
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework:spring-jdbc'
implementation 'org.springframework:spring-tx'
implementation 'org.postgresql:postgresql'
implementation 'org.aspectj:aspectjrt'
implementation 'org.aspectj:aspectjweaver'
implementation 'org.aspectj:aspectjtools'
implementation 'org.springframework:spring-aspects:5.3.2'
implementation 'org.springframework:spring-instrument:5.3.2'
}
test {
useJUnitPlatform()
}
DataConfig.class
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
public class DataConfig {
@Bean
public DataSource postgres() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres?serverTimezone=UTC");
dataSource.setUsername("postgres");
dataSource.setPassword("admin");
dataSource.setSchema("public");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(postgres());
}
}
MainDAO.class
@Repository
public class MainDAO {
private final JdbcTemplate jdbcTemplate;
public MainDAO(DataSource postgres) {
this.jdbcTemplate = new JdbcTemplate(postgres);
}
public Integer getSoundsCount() {
return jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM Sound", Integer.class);
}
@Transactional(propagation = Propagation.MANDATORY)
public void insertSound() {
insertAuthor();
jdbcTemplate.update(
"INSERT INTO Sound (author, name, id) VALUES (?,?,?)",
0, "Spring", 0);
}
}
当我从我的服务中调用方法 insertSound 时,它 运行 无一例外。 但它应该抛出异常,因为 insertSound 方法有 propogation.MANDATORY.
如果我将 EnableTransactionManegment 的 Advice 模式更改为 mode=Advice.PROXY 然后我得到异常
但是模式=Advice.ASPECTJ,事务不工作。
我也尝试使用带有注释 EnableLoadTimeWeaving 的 运行 应用程序并将库 spring-instrument 设置为 java 代理,但它也无法处理事务:
我应该怎么做才能使交易与模式一起工作=Advice.ASPECTJ?
加载时编织 (LTW)
为了使它与 LTW 一起工作,您可以在命令行上结合使用 -javaagent:path/to/aspectjweaver.jar
和 -javaagent:path/to/spring-instrument.jar
,并将您之前提到的 @EnableLoadTimeWeaving
添加到您的配置中。
编译时编织 (CTW)
我找到了使 Spring 的本机 AspectJ 声明性事务与编译时编织一起工作的方法,请参阅我的 pull request。其他细节中的一个关键是:
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(h2());
// Make native AspectJ declarative transactions work with compile-time weaving
AnnotationTransactionAspect.aspectOf().setTransactionManager(transactionManager);
return transactionManager;
}
另请参阅
当 运行 应用程序正常时(即没有任何 -javaagent
参数,因为事务方面已经被编译)在 mvn compile
之后,控制台日志应该显示 Native AspectJ active = true
每次调用 URI sounds/add
时。该日志行由我为说明添加的调试语句触发:
@Transactional//(propagation = Propagation.MANDATORY)
public void insertSound() {
boolean nativeAspectjActive = Arrays
.stream(new Exception().getStackTrace())
.map(StackTraceElement::toString)
.anyMatch(signature -> signature.contains("MainDAO.insertSound_aroundBody"));
logger.info("Native AspectJ active = " + nativeAspectjActive);
// (...)
}