рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рджреАрдк рд╡рд┐рд╕рд░реНрдЬрди рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ @Conditional рдПрдиреЛрдЯреЗрд╢рди рдХреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдореЛрдВрдЧреЛ рдФрд░ MySQL рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд░реНрдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди ред
рдореЗрд░реА рдкреЛрд╕реНрдЯ рдореЗрдВ тАЬ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдХреНрдпреЛрдВ? "рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХреА рдЧрдИ, рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рдЖрдк рд╢рд╛рдпрдж рд╣реА рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкрд░реНрджреЗ рдХреЗ рдкреАрдЫреЗ рдХреНрдпрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИред рд╢рд╛рдпрдж рдЖрдк рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдСрдЯреЛ-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЬрд╛рджреВ рдХреЛ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рд╡рд╕рдВрдд рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ @Conditional рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реАрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП , рдЬреЛ рд╕рднреА рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдСрдЯреЛ-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЬрд╛рджреВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред
рдЕрдиреНрд╡реЗрд╖рдг @Conditional рд╕реБрд╡рд┐рдзрд╛рдПрдБ
рд╡рд╕рдВрдд рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рд╕реЗрдо рдШрдЯрдХреЛрдВ рдХреЛ рд╕рд╢рд░реНрдд рд░реВрдк рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдбреЗрдЯрд╛рд╕реЛрд░реНрд╕ рдмреАрди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХрд┐ рдбреАрдИрд╡реА рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдЙрддреНрдкрд╛рджрди рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░реЛрдбрдХреНрд╢рди рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред
рдЖрдк рдбреЗрдЯрд╛рдмреЗрд╕ рдХрдиреЗрдХреНрд╢рди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рдЧреБрдг рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд░реНрдпрд╛рд╡рд░рдг рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬрдм рднреА рдЖрдкрдХреЛ рдПрдХ рдЕрд▓рдЧ рд╡рд╛рддрд╛рд╡рд░рдг рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ред
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдкреНрд░рд┐рдВрдЧ 3.1 рдиреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ (рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓) рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдкреЗрд╢ рдХреА ред рдЖрдк рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреА рдХрдИ рдмреАрдиреНрд╕ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЬрдм рдЖрдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╕рдХреНрд░рд┐рдп рдкреНрд░реЛрдлрд╛рдЗрд▓ рд╕реЗ рдЬреБрдбрд╝реЗ рдЖрд╡рд╢реНрдпрдХ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдФрд░ рдШрдЯрдХреЛрдВ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдХреЗрд╡рд▓ рдЗрди рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
@Configuration
public class AppConfig
{
@Bean
@Profile("DEV")
public DataSource devDataSource() {
...
}
@Bean
@Profile("PROD")
public DataSource prodDataSource() {
...
}
}
рдлрд┐рд░ рдЖрдк рд╕рд┐рд╕реНрдЯрдо рдкреНрд░реЙрдкрд░реНрдЯреА - Dspring.profiles.active = DEV рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдХреНрд░рд┐рдп рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕рд░рд▓ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕реЗ рд╕рдХреНрд░рд┐рдп рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдШрдЯрдХ рдкрдВрдЬреАрдХрд░рдг рдХреЛ рд╕рдХреНрд╖рдо рдпрд╛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдХреБрдЫ рд╕рд╢рд░реНрдд рддрд░реНрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмреАрди рдШрдЯрдХреЛрдВ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реА рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред
bean- Spring, Spring 4 @Conditional. @Conditional, , .
, , :
- classpath
- Spring bean ApplicationContext
- /
, , .
, Spring's @Conditional.
, UserDAO . UserDAO, JdbcUserDAO, MySQL, MongoUserDAO, MongoDB.
JdbcUserDAO MongoUserDAO System Property, , dbType.
: java -jar myapp.jar -DdbType = MySQL, JdbcUserDAO. , : java -jar myapp.jar -DdbType = MONGO, MongoUserDAO.
JdbcUserDAO MongoUserDAO UserDAO :
public interface UserDAO
{
List<String> getAllUserNames();
}
public class JdbcUserDAO implements UserDAO
{
@Override
public List<String> getAllUserNames()
{
System.out.println("**** Getting usernames from RDBMS *****");
return Arrays.asList("Siva","Prasad","Reddy");
}
}
public class MongoUserDAO implements UserDAO
{
@Override
public List<String> getAllUserNames()
{
System.out.println("**** Getting usernames from MongoDB *****");
return Arrays.asList("Bond","James","Bond");
}
}
Condition MySQLDatabaseTypeCondition, , System Property dbType ┬лMYSQL┬╗ :
public class MySQLDatabaseTypeCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata)
{
String enabledDBType = System.getProperty("dbType");
return (enabledDBType != null && enabledDBType.equalsIgnoreCase("MYSQL"));
}
}
Condition MongoDBDatabaseTypeCondition, , System Property dbType ┬лMONGODB┬╗ :
public class MongoDBDatabaseTypeCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata)
{
String enabledDBType = System.getProperty("dbType");
return (enabledDBType != null && enabledDBType.equalsIgnoreCase("MONGODB"));
}
}
bean- JdbcUserDAO MongoUserDAO, @Conditional :
@Configuration
public class AppConfig
{
@Bean
@Conditional(MySQLDatabaseTypeCondition.class)
public UserDAO jdbcUserDAO(){
return new JdbcUserDAO();
}
@Bean
@Conditional(MongoDBDatabaseTypeCondition.class)
public UserDAO mongoUserDAO(){
return new MongoUserDAO();
}
}
: java -jar myapp.jar -DdbType = MYSQL, bean- JdbcUserDAO.
System property: -DdbType = MONGODB, bean- MongoUserDAO.
, System Property.
, bean- MongoUserDAO , classpath Java MongoDB "com.mongodb.Server", , bean- JdbcUserDAO.
Condition MongoDB "com.mongodb.Server" :
public class MongoDriverPresentsCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext,AnnotatedTypeMetadata metadata)
{
try {
Class.forName("com.mongodb.Server");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
public class MongoDriverNotPresentsCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata)
{
try {
Class.forName("com.mongodb.Server");
return false;
} catch (ClassNotFoundException e) {
return true;
}
}
}
, bean- classpath.
bean- MongoUserDAO, Spring- UserDAO .
Condition, , - bean- , :
public class UserDAOBeanNotPresentsCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata)
{
UserDAO userDAO = conditionContext.getBeanFactory().getBean(UserDAO.class);
return (userDAO == null);
}
}
bean- MongoUserDAO, app.dbType = MONGO?
Condition :
public class MongoDbTypePropertyCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata metadata)
{
String dbType = conditionContext.getEnvironment()
.getProperty("app.dbType");
return "MONGO".equalsIgnoreCase(dbType);
}
}
Condition. Condition . Condition MYSQL MongoDB DatabaseType :
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Conditional(DatabaseTypeCondition.class)
public @interface DatabaseType
{
String value();
}
DatabaseTypeCondition, DatabaseType :
public class DatabaseTypeCondition implements Condition
{
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata metadata)
{
Map<String, Object> attributes = metadata.getAnnotationAttributes(DatabaseType.class.getName());
String type = (String) attributes.get("value");
String enabledDBType = System.getProperty("dbType","MYSQL");
return (enabledDBType != null && type != null && enabledDBType.equalsIgnoreCase(type));
}
}
@DatabaseType :
@Configuration
@ComponentScan
public class AppConfig
{
@Bean
@DatabaseType("MYSQL")
public UserDAO jdbcUserDAO(){
return new JdbcUserDAO();
}
@Bean
@DatabaseType("MONGO")
public UserDAO mongoUserDAO(){
return new MongoUserDAO();
}
}
DatabaseType dbType , , .
, , , @Conditional.
Spring Boot @Conditional bean- .
Condition, SpringBoot org.springframework.boot.autoconfigure spring-boot-autoconfigure-{version}.jar.
Spring Boot @Conditional , .
?
, .
Spring Boot AutoConfiguration
Spring Boot тАФ @EnableAutoConfiguration. , , @SpringBootApplication, , , :
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application
{
}
@EnableAutoConfiguration Spring ApplicationContext , .
Spring Boot AutoConfiguration spring-boot-autoconfigure-{version}.jar, .
AutoConfiguration @Configuration, Spring, @EnableConfigurationProperties .
, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration
{
...
...
@Conditional(DataSourceAutoConfiguration.EmbeddedDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedConfiguration {
}
@Configuration
@ConditionalOnMissingBean(DataSourceInitializer.class)
protected static class DataSourceInitializerConfiguration {
@Bean
public DataSourceInitializer dataSourceInitializer() {
return new DataSourceInitializer();
}
}
@Conditional(DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
protected static class NonEmbeddedConfiguration {
@Autowired
private DataSourceProperties properties;
@Bean
@ConfigurationProperties(prefix = DataSourceProperties.PREFIX)
public DataSource dataSource() {
DataSourceBuilder factory = DataSourceBuilder
.create(this.properties.getClassLoader())
.driverClassName(this.properties.getDriverClassName())
.url(this.properties.getUrl()).username(this.properties.getUsername())
.password(this.properties.getPassword());
if (this.properties.getType() != null) {
factory.type(this.properties.getType());
}
return factory.build();
}
}
...
...
@Configuration
@ConditionalOnProperty(prefix = "spring.datasource", name = "jmx-enabled")
@ConditionalOnClass(name = "org.apache.tomcat.jdbc.pool.DataSourceProxy")
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
@ConditionalOnMissingBean(name = "dataSourceMBean")
protected static class TomcatDataSourceJmxConfiguration {
@Bean
public Object dataSourceMBean(DataSource dataSource) {
....
....
}
}
...
...
}
DataSourceAutoConfiguration @ConditionalOnClass({DataSource.class,EmbeddedDatabaseType.class}), , bean- DataSourceAutoConfiguration , DataSource.class EmbeddedDatabaseType.class classpath.
@EnableConfigurationProperties(DataSourceProperties.class), application.properties DataSourceProperties.
@ConfigurationProperties(prefix = DataSourceProperties.PREFIX)
public class DataSourceProperties implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
public static final String PREFIX = "spring.datasource";
...
...
private String driverClassName;
private String url;
private String username;
private String password;
...
}
, spring.datasource.*, DataSourceProperties.
spring.datasource.url=jdbc:mysql:
spring.datasource.username=root
spring.datasource.password=secret
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
bean-, SpringBoot, @ConditionalOnMissingBean, @ConditionalOnClass @ConditionalOnProperty ..
bean- ApplicationContext, .
spring-boot-autoconfigure-{version}.jar, :
- org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
- org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
- org.springframework.boot.autoconfigure.jackson.JacksonAutoConfigurationetc, рдЗрддреНрдпрд╛рджрд┐ред
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЕрдм рдЖрдкрдХреЛ рд╕рдордЭ рдореЗрдВ рдЖ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдСрдЯреЛрдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди @ рдСрдЯреЛрдХреИрдбреНрдпреВрдЕрд▓ рдлреАрдЪрд░реНрд╕ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╡рд┐рднрд┐рдиреНрди рдСрдЯреЛрдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рд╡рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ ред