Spring是相当吊的项目,多数场景下均是通过XML配置的方式使用它,下面简单介绍如何通过JavaConfig方式进行配置。说个题外话,之所以研究JavaConfig是我在研究spring security的时候,中文材料少的可怜,找到了一篇外文博客,写的还是很赞的,Spring Security 4 Hibernate Integration Annotation+XML Example,博文下面有项目下载地址,该项目零XML配置,下面就通过该项目介绍。
HibernateConfiguration.java类:该类的作用可等同applicationContext.xml,个人觉得类名取得不直观,但是要影响关键是说下类上面的注解的作用。
package com.websystique.springsecurity.configuration;
import java.util.Properties;
import javax.annotation.Resource;
import javax.sql.DataSource;
import com.websystique.springsecurity.dao.UserDao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//说明类为IoC容器
@Configuration
//事务
@EnableTransactionManagement
//指定自动扫描包
@ComponentScan(basePackages = { "com.websystique.springsecurity" })
//配置文件
@PropertySource(value = { "classpath:application.properties" })
//指定使用CGLIB代理,并开启
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class HibernateConfiguration {
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.websystique.springsecurity.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
在HibernateConfiguration类中数据库源,事务,session工厂均有代码,很直观。
下面介绍如何集成Junit4,
很多资源spring-test与Junit4集成均是基于applicationContext.xml的,但是我们这里没有配置文件,所以需要做些改变:
新建一个基本的测试配置类:
package config;
import com.websystique.springsecurity.configuration.HibernateConfiguration;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional;
/**
* Created by li on 2016/1/14.
*/
//指定测试类的运行者
@RunWith(SpringJUnit4ClassRunner.class)
//指定spring配置类
@ContextConfiguration(classes = {HibernateConfiguration.class})
//@WebAppConfiguration is a class-level annotation that is used to declare
//that the ApplicationContext loaded for an integration test should be a WebApplicationContext.
@WebAppConfiguration
@Transactional
public class TestConfig {
}
这里主要是ContextConfiguration的类要和上面的配置类对应好,下面集成Junit
进行
单元测试只要集成该基本类就可以了。下面进行单元测试:
package com.websystique.springsecurity.service;
import config.TestConfig;
import org.junit.Test;
import javax.annotation.Resource;
import static org.junit.Assert.assertNotNull;
/**
* Created by li on 2016/1/14.
*/
public class UserServiceImplTest extends TestConfig{
@Resource(name = "userServiceImpl")
UserServiceImpl userServiceImpl;
@Test
public void testUserServiceClass() throws Exception {
assertNotNull(userServiceImpl);
System.out.println(userServiceImpl.getClass());
}
}
注意:UserServiceImpl 集成了接口,正是使用的CGLIB做代理,所以才没有报错。
PS:
其中@EnableAspectJAutoProxy(proxyTargetClass = true)是我加入的,目的指定CLGLIB作为代理,是防止在Bean继承接口的,抛出nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'userServiceImpl' must be of type [com.websystique.springsecurity.service.UserServiceImpl], but was actually of type [com.sun.proxy.$Proxy43]异常。当然需要添加Maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>