注释 @ActiveProfile 在 Spring 应用程序中不起作用
Posted
技术标签:
【中文标题】注释 @ActiveProfile 在 Spring 应用程序中不起作用【英文标题】:Annotations @ActiveProfile doesn't work in a Spring app 【发布时间】:2021-08-25 21:15:32 【问题描述】:我没有在这个应用程序中使用 spring-boot。 我正在测试配置文件以在集成测试中使用不同的数据源。
我有如下实体用户:
@Table(name = "user_inf")
@Entity
@NamedQuery(name="User.findById", query="select u from User u where u.id=:id")
public class User implements Serializable
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "userName", length = 25)
private String userName;
@Column(name = "userEmail", unique = true, length = 320)
private String userEmail;
对于那个实体,我有服务和 dao(服务只调用 dao 方法)
用户道:
@Repository
@Transactional
public class UserDaoImpl implements UserDao
@PersistenceContext
private EntityManager entityManager;
@Override
public User findById(Long id)
TypedQuery<User> query = entityManager.createNamedQuery("User.findById", User.class);
query.setParameter("id", id);
return query.getSingleResult();
用户服务:
@Service
public class UserServiceImpl implements UserService
@Autowired
private UserDao userDao;
@Override
public User getUser(Long id)
return userDao.findById(id);
@Configuration
@PropertySource(value = "classpath:database/jdbc.properties")
@EnableTransactionManagement
@ComponentScan("com.example.test.repository", "com.example.test.service")
public class SpringConfig
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String ENTITY_MANAGER_PACKAGES_TO_SCAN = "com.example.test.entity";
@Autowired
private Environment env;
@Bean
public DataSource dataSource()
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
@Bean
@Profile("test")
public DataSource dataSourceForTest()
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.test.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
@Bean
public PlatformTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean)
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return transactionManager;
private HibernateJpaVendorAdapter vendorAdaptor()
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
return vendorAdapter;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource mainDataSource)
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
entityManagerFactoryBean.setDataSource(mainDataSource);
entityManagerFactoryBean.setPackagesToScan(ENTITY_MANAGER_PACKAGES_TO_SCAN);
entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
return entityManagerFactoryBean;
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
return new PersistenceExceptionTranslationPostProcessor();
private Properties jpaHibernateProperties()
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH, env.getProperty(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put("hibernate.hbm2ddl.auto", "none");
return properties;
用于数据源和休眠的属性文件(jdbc.properties)包含以下内容:
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdatabase
jdbc.username=Bruce
jdbc.password=givanchy
jdbc.test.url=jdbc:mysql://localhost:3306/testdatabase1
hibernate.max_fetch_depth = 3
hibernate.jdbc.fetch_size = 50
hibernate.jdbc.batch_size = 10
hibernate.show_sql = true
hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
申请入口:
public class EntryClass
public static void main(String[] args)
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
User user =userService.getUser(1L);
System.out.println("userName is "+user.getUserName());
它可以正常工作。 但在测试源 我只有一项服务测试来了解配置文件的工作原理
@SpringJUnitConfig(SpringConfig.class)
@ActiveProfiles("test")
class UserServiceImplTest
@Autowired
private UserService userService;
@Test
void getUser()
User user = userService.getUser(5L);
Assertions.assertEquals("Vector", user.getUserName());
我得到“没有合格的 bean”异常,因为有两个数据源类型的 bean,但我设置了它应该使用哪个配置文件?你能解释为什么它不起作用吗?
【问题讨论】:
只是为了确定。您是否使用spring.profiles.active
作为test
启动运行时?如果没有,spring 会自动默认为default
。
@shinjw 我想如果我在测试类中设置@ActiveProfiles 它会起作用。同样在主源中它可以正常工作,因为我不需要数据源进行测试,所以如果我将spring.profiles.active
设置为test
它只适用于测试类?
【参考方案1】:
正常启动时,不会创建带有“test”配置文件的数据源 bean。 (因为没有设置测试配置文件。)
当您将其作为测试运行时,会创建两个数据源 bean。默认创建是因为它没有任何条件,另一个是因为它带有测试配置文件的注释。
只需将@Profile("!test")
添加到默认bean。这样,只有在测试配置文件未激活时才会创建它。
【讨论】:
以上是关于注释 @ActiveProfile 在 Spring 应用程序中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Jackson Object Mapper 在提供扩展配置时不工作,但在 Spring Boot 中提供类级别/字段级别注释时工作