很久之前写过两篇博客:
spring3.0使用annotation完全代替XML
spring3.0使用annotation完全代替XML(续)
用java config来代替XML,当时还遗留下一些问题:
- <tx:annotation-driven />声明性事务等配置无法用简单代码来实现
- web.xml无法去掉
随着servlet 3.0规范以及spring3.1.M2的发布,现在以上的问题也解决了。
先来说说web.xml,有两种方法来替代
(一)annotation
@WebServlet(urlPatterns="/hello")
public class HelloServlet extends HttpServlet {}
servlet3.0增加了@WebServlet, @WebFilter, @WebListener等注解,servlet容器会在classpath扫描并注册所有的标注好的servlet, filter和listener。这种方法只针对你能访问源代码的情况,对于像spring_mvc用到的DispatcherServlet,无法在源码上加annotation,可以用第二种方法来实现bootstrap
(二)ServletContainerInitializer
这是servlet3的一个接口,我们来看看spring-web提供的实现
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> webAppInitializerClasses,
ServletContext servletContext) throws ServletException {
//implemention omitted
}
}
@HandlesTypes也是servlet3中的注解,这里它处理的是WebApplicationInitializer,也就是说servlet容器会扫描classpath,将所有实现了WebApplicationInitializer接口的类传给onStartup方法中的webAppInitializerClasses,并调用onStartup方法来注册servlet。具体的注册代码可以这样写:
public class WebInit implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
sc.addFilter("hibernateFilter", OpenSessionInViewFilter.class).addMappingForUrlPatterns(null, false, "/*");
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.scan("septem.config.app");
// Manages the lifecycle of the root application context
sc.addListener(new ContextLoaderListener(root));
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.setConfigLocation("septem.config.web");
ServletRegistration.Dynamic appServlet = sc.addServlet("appServlet", new DispatcherServlet(webContext));
appServlet.setLoadOnStartup(1);
appServlet.addMapping("/");
}
}
以上的代码分别调用了sc.addFilter, sc.addListener, sc.addServlet来注册filter, listener和servlet.
用以上的方法就能将WEB-INF/web.xml删除了.spring3.1.M2开始增加了一系列annotation来实现声明性事务及简化spring_mvc配置。WebInit中注册的DispatcherServlet所对应的配置在septem.config.web包里面:
@Configuration
@ComponentScan(basePackages="septem.controller")
@EnableWebMvc
public class WebConfig {
}
一行@EnableWebMvc就导入了spring_mvc需要的诸多bean,再配合@ComponentScan扫描septem.controller包里面所有的@Controller,基本的mvc配置就完成了。
声明性事务也是类似,通过spring root application context扫描包septem.config.app:
@Configuration
@EnableTransactionManagement
public class DataConfig {
@Bean public AnnotationSessionFactoryBean sessionFactory() {
AnnotationSessionFactoryBean sessionFactoryBean = new AnnotationSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setNamingStrategy(new ImprovedNamingStrategy());
sessionFactoryBean.setPackagesToScan("septem.model");
sessionFactoryBean.setHibernateProperties(hProps());
return sessionFactoryBean;
}
private DataSource dataSource() {
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("org.hsqldb.jdbcDriver");
source.setUrl("jdbc:hsqldb:mem:s3demo_db");
source.setUsername("sa");
source.setPassword("");
return source;
}
@Bean public HibernateTransactionManager transactionManager() {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
hibernateTransactionManager.setSessionFactory(sessionFactory().getObject());
return hibernateTransactionManager;
}
private Properties hProps() {
Properties p = new Properties();
p.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
p.put("hibernate.cache.use_second_level_cache", "true");
p.put("hibernate.cache.use_query_cache", "true");
p.put("hibernate.cache.provider_class",
"org.hibernate.cache.EhCacheProvider");
p.put("hibernate.cache.provider_configuration_file_resource_path",
"ehcache.xml");
p.put("hibernate.show_sql", "true");
p.put("hibernate.hbm2ddl.auto", "update");
p.put("hibernate.generate_statistics", "true");
p.put("hibernate.cache.use_structured_entries", "true");
return p;
}
}
DataConfig定义了所有与数据库和hibernate相关的bean,通过@EnableTransactionManagement实现声明性事务。
service是如何注册的呢?
@Configuration
@ComponentScan(basePackages="septem.service")
public class AppConfig {
}
通过@ComponentScan扫描包septem.service里定义的所有service,一个简单service实现如下:
@Service @Transactional
public class GreetingService {
@Autowired
private SessionFactory sessionFactory;
@Transactional(readOnly=true)
public String greeting() {
return "spring without xml works!";
}
@Transactional(readOnly=true)
public Book getBook(Long id) {
return (Book) getSession().get(Book.class, id);
}
@Transactional(readOnly=true)
public Author getAuthor(Long id){
return (Author) getSession().get(Author.class, id);
}
public Book newBook() {
Book book = new Book();
book.setTitle("java");
getSession().save(book);
return book;
}
public Author newAuthor() {
Book book = newBook();
Author author = new Author();
author.setName("septem");
author.addBook(book);
getSession().save(author);
return author;
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
}
这样整个项目中就没有XML文件了。在写这些代码的过程中也碰到不少问题,纪录如下:
(一)项目没有web.xml,maven的war插件要加上failOnMissingWebXml=false
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
(二) tomcat-embeded7.0.16还有点小BUG,不能把DispatcherServlet映射为"/",所以代码里把它映射为"/s3/"
appServlet.addMapping("/s3/");
(三) 如果要使用spring提供的OpenSessionInViewFilter,在定义Hibernate SessionFactory的时候,不能直接new SessionFactory出来,即以下代码是不能实现声明性事务的:
@Bean public SessionFactory sessionFactory() {
org.hibernate.cfg.Configuration config = new org.hibernate.cfg.Configuration();
config.setProperties(hProps());
config.addAnnotatedClass(Book.class);
return config.buildSessionFactory();
}
必须使用spring提供的FactoryBean:
@Bean public AnnotationSessionFactoryBean sessionFactory() {
AnnotationSessionFactoryBean sessionFactoryBean = new AnnotationSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setNamingStrategy(new ImprovedNamingStrategy());
sessionFactoryBean.setPackagesToScan("septem.model");
sessionFactoryBean.setHibernateProperties(hProps());
return sessionFactoryBean;
}
后记:在spring3.1以servlet3中annotation已经是一等公民了,可以实现任何原先只能在xml文件中配置的功能,并具有简洁,静态检查及重构友好等优点。总体上来讲spring提供的“魔法”还是太多了,尤其是跟hibernate,事务,open session in view等机制结合在一起的时候,简洁代码的背后隐藏着太多的依赖关系,如果程序出了问题,排除这些魔法,一层一层地还原程序的本来面目,将是一件很需要耐心的事情
分享到:
相关推荐
### 详解Spring 3.0基于Annotation的依赖注入实现 #### 概述 Spring框架作为一个广泛使用的Java开发框架,提供了强大的依赖注入(Dependency Injection, DI)能力,帮助开发者轻松管理和组织复杂的Java应用。随着...
在Spring 3.0中,批注(Annotation)被更广泛地用于配置,替代了XML配置文件。例如,`@Autowired`用于自动装配依赖,`@Service`、`@Repository`和`@Controller`用于组件的标记,`@Transactional`用于标记事务边界。...
Struts2、Hibernate3.5和Spring3.0是Java Web开发中的三个核心框架,它们在权限管理中扮演着重要角色。这篇详细说明将深入探讨这三个框架如何协同工作,以及如何利用注解(Annotation)来简化配置。 Struts2是一个...
在本文中,我们将深入探讨Spring 3.0框架的配置示例,特别是关于文件上传和AJAX(异步JavaScript及XML)的注解使用。Spring框架是Java领域中广泛使用的轻量级应用框架,它提供了丰富的功能来简化企业级开发。在...
3. **注解驱动的开发(Annotation-based Development)**:Spring 3.0大力推广注解,如@Service、@Repository、@Controller等,使得XML配置文件大大减少,提高了开发效率。 4. **JSR-303/JSR-349 Bean Validation**...
3. **配置Spring3.0**:在applicationContext.xml中声明Bean,包括Service层、DAO层的实例,以及Hibernate的相关配置。通过@Autowired注解实现依赖注入。 4. **整合Struts和Spring**:使用Spring的Struts插件,使...
Spring 3.0版本引入了对定时任务的支持,这是一个非常实用的功能,可以帮助开发者实现定期执行的任务,如数据同步、报表生成等。本文将深入探讨Spring 3.0中的定时任务实现,并结合Quartz库来进一步扩展定时任务的...
4. **配置AOP**:在Spring 3.0中,可以使用XML配置或者注解方式来声明AOP。XML配置通过`<aop:config>`和`<aop:advisor>`等元素定义切入点和通知。注解方式则更加简洁,如`@Aspect`定义切面,`@Pointcut`定义切入点,...
这种方法只需要在 Spring 配置文件中定义一个事务管理对象(如 DataSourceTransactionManager),然后加入 `<tx:annotation-driven/>` 节点,引用该事务管理对象,然后即可在需要进行事务处理的类和方法使用 `@...
总之,这个压缩包中的Spring 3.0 XSD文件是理解和使用Spring框架的关键资源。它们详细地定义了XML配置文件的语法,使得开发者可以更精确地控制Spring容器的行为,实现灵活的依赖注入、AOP、事务管理、数据库和消息...
2. **注解驱动开发(Annotation-based Development)**:在Spring 3.0中,注解成为主流的编程模式,如@Controller、@Service、@Repository和@Transactional等,减少了XML配置,提高了代码的可读性和可维护性。...
注解(Annotation)是Spring 3.0中的一个重要特性,它提供了一种元数据的方式,允许开发者在代码中嵌入信息,这些信息可以被编译器或运行时环境用来处理代码。Spring 3.0引入了如@Component、@Service、@Repository...
2. **注解驱动开发(Annotation-based Development)**:Spring 3.0引入了大量的注解,如@Service、@Controller、@Repository和@Transactional,减少了XML配置,提高了代码可读性。例如,@Autowired用于自动装配依赖,...
Spring 3.0 XSD 文件是Spring框架在3.0版本中使用的XML Schema定义文件,它们主要用于配置Spring框架的应用上下文和服务。XSD文件的作用在于为XML配置提供结构化约束和验证,确保开发者遵循正确的格式编写配置。在...
5. **REST支持**:Spring 3.0增加了对RESTful服务的支持,`org.springframework.web.bind.annotation.RequestMapping`和`@ResponseBody`注解用于处理HTTP请求并返回JSON或XML响应。 6. **JSR-303/JSR-349 Bean ...
在Spring 3.0中,Spring MVC引入了强大的注解支持,使得开发Web应用程序变得更加简洁高效。本节将深入探讨Spring MVC注解及其在实际应用中的实现方式。 首先,Spring MVC注解允许开发者以声明式的方式配置控制器,...
2. **注解驱动开发 (Annotation-based Development)**:Spring 3.0引入了大量的注解,如`@Component`、`@Service`、`@Repository`和`@Controller`,用于简化配置,使代码更加简洁。此外,`@Autowired`和`@Qualifier`...
在本文中,我们将深入探讨如何使用Spring 3.0 MVC框架通过注解方式实现一个简单的“Hello, World!”输出。Spring MVC是Spring框架的一部分,它为构建基于模型-视图-控制器(MVC)架构的Web应用程序提供了一个强大的...