Spring Bean配置的三种不同方式,主要包括:
- 基于XML的配置方式
- 基于注解的配置方式
- 基于Java类的配置方式
在本文中我将结合自己实际情况来介绍第二种基于注解的配置方式
使用注解方式,主要是为了替代xml文件,使开发更加快速。但是,xml文件的使用就是解决修改程序修改源代码,现在又不去使用xml文件,那么不就违背了开闭原则了么,的确是。不过么,注解也有注解的好,使用注解就不用配置那么多的xml文件啦,最重要的是开发效率高。。
在没有使用注解时,spring框架的配置文件applicationContext.xml文件中需要配置很多的<bean>标签,用来声明类对象。使用注解,则不必在配置文件中添加标签拉,对应的是在对应类的“注释”位置添加说明。
首先我在一个web项目集成spring,来介绍这种方法在web中的一些配置
[开发工具]
IDEA,Tomcat
[相应的架包]
这些基本的架包到官网下载或者到这个网站下载http://how2j.cn/
[项目相应的包]
首先是在web下新建一个bean.xml(这个名字自己取不一定需要和我的一样),然后就是里面的内容
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--通过注解扫描的方式来完成相应的注入-->
<context:component-scan base-package="com.wyf" ></context:component-scan>
</beans>
<context:component-scan base-package="com.wyf" ></context:component-scan>
这段代码的意思是通过注解扫描来告诉框架那些类是使用注解的,也就是com.wyf下面的包中的所有类
[注解有哪些]
spring框架使用的是分层的注解。
持久层:@Repository;
服务层:@Service
控制层:@Controller
首先是持久层注解@Repository对应数据访问层Bean
package com.wyf.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void save(){
System.out.print("通过注解扫描成功完成测试");
}
}
这里的@Repository 等同于配置文件中的
<bean id="userDao" class="com.wyf.UserDao" />
服务层注解@Service对应的是业务层Bean
package com.wyf.service;
import com.wyf.dao.UserDao;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(value = "userDao")
public class UserService {
@Resource//相当于自动装配
private UserDao userDao;
public void addUser(){
userDao.save();
}
}
@Resource 对象间关系的组合,默认采用的是byName方式进行装配,如果根据名称查找不到关联的对象,那么会再采用byType继续查找。
@Service注解等同与<bean id="userService" class="com.wyf.UserService" />
控制层注解@Controller对应表现层的Bean,也就是Action
package com.wyf.action;
import com.wyf.service.UserService;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller(value = "userService")
public class UserAction {
@Resource
private UserService userService;
public void addUser(){
userService.addUser();
}
}
@Controller注解等同于<bean id="userService" class="com.wyf.UserAction " />
[补充下]
在Action声明的“userService”变量的类型必须是“UserServiceImpl”或者是其父类“UserService”,否则由于类型不一致而无法注入,由于Action中的声明的“userService”变量使用了@Resource注解去标注,并且指明了其name = "userService",这就等于告诉Spring,说我Action要实例化一个“userService”,你Spring快点帮我实例化好,然后给我,当Spring看到userService变量上的@Resource的注解时,根据其指明的name属性可以知道,Action中需要用到一个UserServiceImpl的实例,此时Spring就会把自己创建好的名字叫做"userService"的UserServiceImpl的实例注入给Action中的“userService”变量,帮助Action完成userService的实例化,这样在Action中就不用通过“UserService userService = new UserServiceImpl();”这种最原始的方式去实例化userService了。如果没有Spring,那么当Action需要使用UserServiceImpl时,必须通过“UserService userService = new UserServiceImpl();”主动去创建实例对象,但使用了Spring之后,Action要使用UserServiceImpl时,就不用主动去创建UserServiceImpl的实例了,创建UserServiceImpl实例已经交给Spring来做了,Spring把创建好的UserServiceImpl实例给Action,Action拿到就可以直接用了。Action由原来的主动创建UserServiceImpl实例后就可以马上使用,变成了被动等待由Spring创建好UserServiceImpl实例之后再注入给Action,Action才能够使用。这说明Action对“UserServiceImpl”类的“控制权”已经被“反转”了,原来主动权在自己手上,自己要使用“UserServiceImpl”类的实例,自己主动去new一个出来马上就可以使用了,但现在自己不能主动去new“UserServiceImpl”类的实例,new“UserServiceImpl”类的实例的权力已经被Spring拿走了,只有Spring才能够new“UserServiceImpl”类的实例,而Action只能等Spring创建好“UserServiceImpl”类的实例后,再“恳求”Spring把创建好的“UserServiceImpl”类的实例给他,这样他才能够使用“UserServiceImpl”,这就是Spring核心思想“控制反转”,也叫“依赖注入”,“依赖注入”也很好理解,Action需要使用UserServiceImpl干活,那么就是对UserServiceImpl产生了依赖,Spring把Acion需要依赖的UserServiceImpl注入(也就是“给”)给Action,这就是所谓的“依赖注入”。对Action而言,Action依赖什么东西,就请求Spring注入给他,对Spring而言,Action需要什么,Spring就主动注入给他。
使用注解声明对象,默认情况下生成的id名称为类名称的首字母小写。
上面的基本配置说完了,接下来就是要说一下web项目中web.xml中配置Spring IOC 容器加载
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置Spring IOC 容器的加载-->
<!-- Spring监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/WEB-INF/bean.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
在实际项目中spring的配置文件applicationcontext.xml是通过spring提供的加载机制自动加载到容器中。在web项目中,配置文件加载到web容器中进行解析。目前,spring提供了两种加载器,以供web容器的加载:一种是ContextLoaderListener,另一种是ContextLoaderServlet。这两种在功能上完全相同,只是前一种是基于Servlet2.3版本中新引入的Listener接口实现,而后一种是基于Servlet接口实现,以下是这两种加载器在web.xml中的配置应用:
ContextLoaderListener
<listener>
<listener-class>org.springframework.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderServlet
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
通过上面的配置,web容器会自动加载applicationcontext.xml初始化。
如果需要指定配置文件的位置,可通过context-param加以指定:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/WEB-INF/bean.xml</param-value>
</context-param>
<param-value>classpath*:/WEB-INF/bean.xml</param-value>
这段代码是我存放bean.xml的目录前面那个classpath*如果没有后面那个*号就会出现
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
反正我当时是这样出错的你们可以借鉴下
如果上面的配置基本完成那么我们运行下index.jsp成功那么说明我们配置ok了
我自己运行成功了