一般对spring比较熟悉得使用xml来注入bean,spring3之后注解则越来越丰富
特别最近使用spring-boot,集成了spring和tomcat等容器,减少了application.xml和web.xml的配置
所以bean的注入都移到了Configuration的class中。
复杂问题简单化:Configuration和xml的配置文件的各属性可一一对应,下面列几个注解本次有用到过的,应该也就是常用的了。
- @Configuration:表示这个class需要spring启动时做配置
- @ComponentScan:此配置上下文需要扫描的package,类似于xml中的配置
<context:component-scan base-package="com.biz.dao.**.*"/>
- @ImportAutoConfiguration(MyBatisConfig.class):引入其他配置的资源,类似于xml中的配置
<import resource="classpath:biz-context.xml"/>
- @Autowired @Resource:在configuration中自动引入bean,此bean应满足三个条件:
- 类定义中有注解@Component:表示是spring扫描时可装载为bean
- 此configuration中扫描包含此类
- 此类中入有@Autowired @Resource的bean需同样满足以上两个条件
类似于xml中的ref属性,例如:
<bean id="logMessage" class="com.***.LogMessage"/>
<bean id="messageFactory" class="com.**.MessageFactoryImpl">
<property name="messageMap">
<map>
<ref key="log" value-ref="logMessage"/>
</map>
</property>
</bean>
- @AutoConfigureAfter(MyBatisConfig.class):表示在MyBatisConfig.class配置完成后加载此配置项
- @AutoConfigureOrder:设定加载顺序,实际操作貌似没啥用
- @EnableTransactionManagement
- @ConfigurationProperties(prefix=”datasource”):spring-boot中用到的,在application.yml中可指定此配置文件的属性,以prefix中指定的datasource为识别key,例如:
class定义:
@Component
@ConfigurationProperties(prefix="datasource")
public class DataBaseConfig {
private String url;
private String username;
private String password;
//get set方法省略
}
application.yml
datasource:
name: datasource
initialize: false
url: jdbc:log4jdbc:mysql://127.0.0.1:3306/es_test?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8
username: root
password: **************
driverClassName: com.mysql.jdbc.Driver
PS:这种场景类似于xml中注入一个bean,bean属性均为常量的情况,例如:
<bean id="datasource" class="com.mysql.jdbc.Driver">
<property name="url" value="127.0.0.1"/>
<property name="username" value="root"/>
<property name="password" value="*****"/>
</bean>
最后举个栗子:
- 首先需要配置数据库
@ComponentScan({ "com.***.conf"})
@Configuration
@EnableTransactionManagement
public class MyBatisConfig implements TransactionManagementConfigurer {
private static final Logger log = LoggerFactory.getLogger(MyBatisConfig.class);
@Autowired
DataBaseConfig dataConfig;
@Bean
public Filter statFilter() {
StatFilter statFilter = new StatFilter();
statFilter.setSlowSqlMillis(5000);
statFilter.setLogSlowSql(true);
statFilter.setMergeSql(true);
return statFilter;
}
@Bean
public Filter logFilter() {
Slf4jLogFilter filter = new Slf4jLogFilter();
filter.setStatementExecutableSqlLogEnable(true);
return filter;
}
@Bean(destroyMethod = "close", initMethod = "init")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(dataConfig.getUrl());
dataSource.setUsername(dataConfig.getUsername());
dataSource.setPassword(dataConfig.getPassword());
dataSource.setDriverClassName("net.sf.log4jdbc.sql.jdbcapi.DriverSpy");
dataSource.setMaxActive(100);
dataSource.setMinIdle(50);
dataSource.setInitialSize(2);
dataSource.setMaxWait(500);
dataSource.setProxyFilters(Lists.<Filter>newArrayList(statFilter(),logFilter()));
return dataSource;
}
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// 分页插件
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
properties.setProperty("reasonable", "true");
properties.setProperty("supportMethodsArguments", "true");
properties.setProperty("returnPageInfo", "check");
properties.setProperty("params", "count=countSql");
properties.setProperty("dialect", "mysql");
properties.setProperty("offsetAsPageNum", "true");
pageHelper.setProperties(properties);
// 添加插件
bean.setPlugins(new Interceptor[] { pageHelper });
Properties configurationProperties = new Properties();
configurationProperties.setProperty("cacheEnabled", "true");
configurationProperties.setProperty("lazyLoadingEnabled", "true");
configurationProperties.setProperty("multipleResultSetsEnabled", "true");
configurationProperties.setProperty("useColumnLabel", "true");
configurationProperties.setProperty("mapUnderscoreToCamelCase", "true");
configurationProperties.setProperty("defaultExecutorType", "REUSE");
configurationProperties.setProperty("defaultStatementTimeout", "25000");
// 添加XML目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
bean.setConfigurationProperties(configurationProperties);
bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
return bean.getObject();
} catch (Exception e) {
log.error("[MyBatisConfig-sqlSessionFactoryBean]error", e);
throw new RuntimeException(e);
}
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
- 然后配置各种bean
@ComponentScan({"com.**.message","com.**.service.*","com.**.dao.*"})
@Configuration
@ImportAutoConfiguration(MyBatisConfig.class)
public class BeanConfig {
@Autowired
LogMessage logMessage;//只有ComponentScan过的bean才能在这里自动绑定
@Bean(name = "messageFactory")
public MessageFactory messageFactoryBean(){
MessageFactoryImpl factory = new MessageFactoryImpl();
Map<MessageType,CommunicateMessage> map = Maps.newHashMap();
map.put(MessageType.LOG_MESSAGE,logMessage);
factory.setMessageMap(map);
return factory;
}
}
总结:配置时遇到了一些问题,例如@Autowire后编译错误(是因为没有@ComponentScan相应的包),网上资料说破坏了加载顺序什么的要定义为static,定义为static后注入bean始终为null(当然了,只是初始化占了一个static位置而已,并未真正注入)。这些问题归根到底是因为不了解@Configuration的加载原理。总之,了解了spring加载顺序,理解@Configuration的class和xml配置文件一一对应,另外了解各注解使用方法即可顺当地做配置~(≧▽≦)/~啦啦啦