Skip to content

Commit

Permalink
解决AOP增强Mapper层导致的错误.
Browse files Browse the repository at this point in the history
  • Loading branch information
nieqiurong committed Oct 25, 2023
1 parent d5a91d9 commit 08cf31f
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 7 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ext {
"spring-tx" : "org.springframework:spring-tx:${springVersion}",
"spring-web" : "org.springframework:spring-web:${springVersion}",
"spring-aop" : "org.springframework:spring-aop:${springVersion}",
"aspectjrt" : "org.aspectj:aspectjrt:1.9.20.1",
"aspectjweaver" : "org.aspectj:aspectjweaver:1.9.20.1",
"cglib" : "cglib:cglib:3.3.0",
"imadcn" : "com.imadcn.framework:idworker:1.5.0",
"spring-cloud-commons" : "org.springframework.cloud:spring-cloud-commons:${springCloudVersion}",
Expand Down
2 changes: 1 addition & 1 deletion mybatis-plus-extension/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ dependencies {
implementation "com.github.ben-manes.caffeine:caffeine:2.9.3"
testImplementation "com.github.pagehelper:pagehelper:5.3.1"
testImplementation "com.google.guava:guava:31.1-jre"
testImplementation "io.github.classgraph:classgraph:+"
testImplementation "io.github.classgraph:classgraph:4.8.163"
testImplementation "${lib.h2}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
Expand All @@ -57,6 +59,17 @@
@SuppressWarnings("unchecked")
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {

private static boolean loadAop = false;

static {
try {
ClassUtils.toClassConfident("org.springframework.aop.framework.AopProxyUtils");
loadAop = true;
} catch (Exception exception) {
// ignore
}
}

private final ConversionService conversionService = DefaultConversionService.getSharedInstance();

protected final Log log = LogFactory.getLog(getClass());
Expand All @@ -82,14 +95,22 @@ public Class<T> getEntityClass() {

private volatile SqlSessionFactory sqlSessionFactory;

@SuppressWarnings("rawtypes")
@SuppressWarnings({"rawtypes", "deprecation"})
protected SqlSessionFactory getSqlSessionFactory() {
if (this.sqlSessionFactory == null) {
synchronized (this) {
if (this.sqlSessionFactory == null) {
MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(this.baseMapper);
SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
Object target = this.baseMapper;
if (loadAop && AopUtils.isAopProxy(this.baseMapper)) {
target = AopProxyUtils.getSingletonTarget(this.baseMapper);

This comment has been minimized.

Copy link
@refeccd

refeccd Oct 25, 2023

这个地方,有没有可能不一定是 Singleton?

This comment has been minimized.

Copy link
@refeccd

refeccd Oct 25, 2023

看了下org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
	this.advisedBeans.put(cacheKey, Boolean.TRUE);
	Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
	this.proxyTypes.put(cacheKey, proxy.getClass());
	return proxy;
}

虽然在创建代理时大部分都是在AbstractAutoProxyCreator#postProcessAfterInitialization里创建的
但是也有可能是在AbstractAutoProxyCreator#postProcessBeforeInstantiation里创建的代理。
postProcessBeforeInstantiation里可以通过getCustomTargetSource为 bean 返回一个自定义的TargetSource
这个时候不一定是 SingletonTargetSource@nieqiurong

}
if (target != null) {
MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(target);
SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
} else {
this.sqlSessionFactory = GlobalConfigUtils.currentSessionFactory(this.entityClass);
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion mybatis-plus/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ dependencies {
testImplementation "${lib.'javax.servlet-api'}"

testImplementation "${lib.'spring-test'}"

testImplementation "${lib.'spring-aop'}"
testImplementation "${lib.'aspectjweaver'}"
testImplementation "${lib."jackson"}"
testImplementation "${lib."fastjson"}"
testImplementation "${lib."gson"}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
* @author nieqiurong
*/
@Aspect
@EnableAspectJAutoProxy
public class AopConfig1 {

private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig1.class);

@Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
public void point() {
}

@Before("point()")
public void before() {
LOGGER.info("before ...");
}

@After("point()")
public void after() {
LOGGER.info("After ...");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author nieqiurong
*/
@Aspect
public class AopConfig2 {

private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig2.class);

@Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
public void point() {
}

@Before("point()")
public void before() {
LOGGER.info("before ...");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.h2.Driver;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

import javax.sql.DataSource;

/**
* @author nieqiurong
*/
@Configuration
@ComponentScan("com.baomidou.mybatisplus.test.h2.issues.aop")
@MapperScan("com.baomidou.mybatisplus.test.h2.issues.aop.mapper")
public class AppConfig {

@Bean
public DataSource dataSource() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new Driver());
dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
return mybatisSqlSessionFactoryBean.getObject();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
import org.apache.ibatis.jdbc.SqlRunner;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

/**
* @author nieqiurong
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class, AopConfig2.class})
public class MultiAopTest {

@Autowired
private IDemoService demoService;

@Autowired
private DataSource dataSource;

@Test
void test() throws SQLException {
new SqlRunner(dataSource.getConnection()).run(
"""
CREATE TABLE IF NOT EXISTS demo (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NULL DEFAULT NULL ,
PRIMARY KEY (id)
);
"""
);
demoService.save(new Demo());
demoService.saveBatch(List.of(new Demo()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
import org.apache.ibatis.jdbc.SqlRunner;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

/**
* @author nieqiurong
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class})
public class NoAopTest {

@Autowired
private IDemoService demoService;

@Autowired
private DataSource dataSource;

@Test
void test() throws SQLException {
new SqlRunner(dataSource.getConnection()).run(
"""
CREATE TABLE IF NOT EXISTS demo (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NULL DEFAULT NULL ,
PRIMARY KEY (id)
);
"""
);
demoService.save(new Demo());
demoService.saveBatch(List.of(new Demo()));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.baomidou.mybatisplus.test.h2.issues.aop;

import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
import org.apache.ibatis.jdbc.SqlRunner;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

/**
* @author nieqiurong
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class, AopConfig1.class})
public class SingleAopTest {

@Autowired
private IDemoService demoService;

@Autowired
private DataSource dataSource;

@Test
void test() throws SQLException {
new SqlRunner(dataSource.getConnection()).run(
"""
CREATE TABLE IF NOT EXISTS demo (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NULL DEFAULT NULL ,
PRIMARY KEY (id)
);
"""
);
demoService.save(new Demo());
demoService.saveBatch(List.of(new Demo()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.baomidou.mybatisplus.test.h2.issues.aop.entity;

import lombok.Data;

/**
* @author nieqiurong
*/
@Data
public class Demo {

private Long id;

private String name;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.baomidou.mybatisplus.test.h2.issues.aop.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
import org.apache.ibatis.annotations.Mapper;

/**
* @author nieqiurong
*/
@Mapper
public interface DemoMapper extends BaseMapper<Demo> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.baomidou.mybatisplus.test.h2.issues.aop.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;

/**
* @author nieqiurong
*/
public interface IDemoService extends IService<Demo> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.baomidou.mybatisplus.test.h2.issues.aop.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
import com.baomidou.mybatisplus.test.h2.issues.aop.mapper.DemoMapper;
import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
import org.springframework.stereotype.Service;

/**
* @author nieqiurong
*/
@Service
public class DemoServiceImpl extends ServiceImpl<DemoMapper, Demo> implements IDemoService {

}

0 comments on commit 08cf31f

Please sign in to comment.