spring注解和一些配置

时间:2021-11-27 20:34:28

Spring注解

1.准备工作
(1)导入common-annotations.jar
(2)导入schema文件 文件名为spring-context-2.5.xsd
(3)在xml的beans节点中配置

2.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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-default-lazy-init="true">
<!--将针对注解的处理器配置好 -->
<context:annotation-config />
<!-- 使用annotation定义事务-->
<tx:annotation-driventransaction-managertx:annotation-driventransaction-manager="transactionManager" proxy-target-class="true"/>
<!--使用annotation 自动注册bean,并检查@Required,@Autowired的属性已被注入base-package为需要扫描的包(含所有子包)-->
<context:component-scanbase-packagecontext:component-scanbase-package="com" />
.....
<beans>

注:
该配置隐式注册了多个对注解进行解析的处理器,如:
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
其实,注解本身做不了任何事情,和XML一样,只起到配置的作用,主要在于背后强大的处理器,其中就包括了配置项里面的注解所使用的处理器,所以配置了

 <context:component-scanbase-package="">之后,便无需再配置<context:annotation-config>

1.在java代码中使用@Autowired或@Resource注解方式进行装配 ,这两个注解的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到名称匹配的bean才会按类型装配。
@Autowired一般装配在set方法之上,也可以装配在属性上边,但是在属性上边配置,破坏了java的封装,所以一般不建议使用

@Autowired是根据类型进行自动装配的。如果当Spring上下文中存在不止一个所要装配类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在所要装配类型的bean,也会抛出BeanCreationException异常。我们可以使用@Qualifier配合@Autowired来解决这些问题。

[java] view plaincopy
 @Autowired    
public void setUserDao(@Qualifier("userDao") UserDao userDao) {
this.userDao = userDao;
}

这样,Spring会找到id为userDao的bean进行装配。

可能不存在UserDao实例
[java] view plaincopy

  @Autowired(required = false)     
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

2.@Resource(JSR-250标准注解,推荐使用它来代替Spring专有的@Autowired注解)Spring 不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName自动注入罢了。@Resource有两个属性是比较重要的,分别是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略
@Resource装配顺序

1 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

2 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

3 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

4 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(见2);如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配;

  1. @PostConstruct(JSR-250)
    在方法上加上注解@PostConstruct,这个方法就会在Bean初始化之后被Spring容器执行(注:Bean初始化包括,实例化Bean,并装配Bean的属性(依赖注入))。
    它的一个典型的应用场景是,当你需要往Bean里注入一个其父类中定义的属性,而你又无法复写父类的属性或属性的setter方法时,如:

[java] view plaincopy

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {     
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
this.mySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
super.setSessionFactory(mySessionFacotry);
} }

这里通过@PostConstruct,为UserDaoImpl的父类里定义的一个sessionFactory私有属性,注入了我们自己定义的sessionFactory(父类的setSessionFactory方法为final,不可复写),之后我们就可以通过调用super.getSessionFactory()来访问该属性了。
4.@PreDestroy(JSR-250)
在方法上加上注解@PreDestroy,这个方法就会在Bean初始化之后被Spring容器执行。由于我们当前还没有需要用到它的场景,这里不不去演示。其用法同@PostConstruct。
5.使用Spring注解完成Bean的定义
以上我们介绍了通过@Autowired或@Resource来实现在Bean中自动注入的功能,下面我们将介绍如何注解Bean,从而从XML配置文件中完全移除Bean定义的配置。
@Component:只需要在对应的类上加上一个@Component注解,就将该类定义为一个Bean了:

[java] view plaincopy

@Component    
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
...
}

使用@Component注解定义的Bean,默认的名称(id)是小写开头的非限定类名。如这里定义的Bean名称就是userDaoImpl。你也可以指定Bean的名称:
@Component(“userDao”)
@Component是所有受Spring管理组件的通用形式,Spring还提供了更加细化的注解形式:@Repository、@Service、@Controller,它们分别对应存储层Bean,业务层Bean,和展示层Bean。目前版本(2.5)中,这些注解与@Component的语义是一样的,完全通用,在Spring以后的版本中可能会给它们追加更多的语义。所以,我们推荐使用@Repository、@Service、@Controller来替代@Component。

6.使用让Bean定义注解工作起来

<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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.bzu" />
</beans>

@Service服务层组件,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,例如Chinese实例化为chinese,如果需要自己改名字则:@Service("你自己改的bean名")。

@Controller用于标注控制层组件(如struts中的action)

@Repository持久层组件,用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。


Spring mvc中@RequestMapping 6个基本用法小结

博客分类: JAVA相关
springmvc
小结下spring mvc中的@RequestMapping的用法。

1)最基本的,方法级别上应用,例如:

Java代码 收藏代码

@RequestMapping(value="/departments")  
public String simplePattern(){

System.out.println("simplePattern method was called");
return "someResult";

}

则访问http://localhost/xxxx/departments的时候,会调用 simplePattern方法了

2) 参数绑定

Java代码 收藏代码

@RequestMapping(value="/departments")  
public String findDepatment(
@RequestParam("departmentId") String departmentId){
System.out.println("Find department with ID: " + departmentId);
return "someResult";
}

形如这样的访问形式:

/departments?departmentId=23就可以触发访问findDepatment方法了

3 REST风格的参数

Java代码 收藏代码

@RequestMapping(value="/departments/{departmentId}")  
public String findDepatment(@PathVariable String departmentId){
System.out.println("Find department with ID: " + departmentId);
return "someResult";
}

形如REST风格的地址访问,比如:
/departments/23,其中用(@PathVariable接收rest风格的参数

4 REST风格的参数绑定形式之2
先看例子,这个有点象之前的:
Java代码 收藏代码

@RequestMapping(value="/departments/{departmentId}")  
public String findDepatmentAlternative(
@PathVariable("departmentId") String someDepartmentId){

System.out.println("Find department with ID: " + someDepartmentId);
return "someResult";

}

这个有点不同,就是接收形如/departments/23的URL访问,把23作为传入的departmetnId,,但是在实际的方法findDepatmentAlternative中,使用
@PathVariable(“departmentId”) String someDepartmentId,将其绑定为
someDepartmentId,所以这里someDepartmentId为23

5 url中同时绑定多个id

Java代码 收藏代码

@RequestMapping(value="/departments/{departmentId}/employees/{employeeId}")  
public String findEmployee(
@PathVariable String departmentId,
@PathVariable String employeeId){

System.out.println("Find employee with ID: " + employeeId +
" from department: " + departmentId);
return "someResult";

}

这个其实也比较好理解了。

6 支持正则表达式

Java代码 收藏代码

@RequestMapping(value="/{textualPart:[a-z-]+}.{numericPart:[\\d]+}")  
public String regularExpression(
@PathVariable String textualPart,
@PathVariable String numericPart){

System.out.println("Textual part: " + textualPart +
", numeric part: " + numericPart);
return "someResult";
}

比如如下的URL:/sometext.123,则输出:
Textual part: sometext, numeric part: 123.


1) 普通path路径

@RequestMapping(value = "/foos")
@ResponseBody
public String getFoosBySimplePath() {
return "Get some Foos";
}

然后尝试用curl请求下
curl -i http://localhost:8080/spring-mvc/foos

2) 指定RequestMethod.POST

@RequestMapping(value = "/foos", method = RequestMethod.POST)
@ResponseBody
public String postFoos() {
return "Post some Foos";
}
curl i -X POST http://localhost:8080/spring-mvc/foos
3) 指定http请求头
@RequestMapping(value = "/foos", headers = "key=val")
@ResponseBody
public String getFoosWithHeader() {
return "Get some Foos with Header";
}

其中在headers可以跟多个了,如:

RequestMapping(value = "/foos", headers = { "key1=val1", "key2=val2" })
@ResponseBody
public String getFoosWithHeaders() {
return "Get some Foos with Header";
}

注意curl的请求为:
curl -i -H “key:val” http://localhost:8080/spring-mvc/foos

4)@RequestMapping中的新的product和consume.
在spring 3.0中,可以指定请求头的media格式,如:

@RequestMapping(value = "/foos", method = RequestMethod.GET, headers = "Accept=application/json")
@ResponseBody
public String getFoosAsJsonFromBrowser() {
return "Get some Foos with Header Old";
}

curl测试:
curl -H “Accept:application/json,text/html” http://localhost:8080/spring-mvc/foos

如果在3.1中,则有新的 produces和consume的属性了,如:

@RequestMapping(value = "/foos", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public String getFoosAsJsonFromREST() {
return "Get some Foos with Header New";
}

如果用3.1,但依然用旧的方式,则旧的方式的请求都会自动变成produces和consume了;
@RequestMapping(value=”/testMsgConverter”,consumes=”text/plain”,produces=”application/json”)

表示handlermethod接受的请求的header中的 Content-Type为text/plain;
Accept为application/json

5) @PathVariable
1 单一的

@RequestMapping(value = "/foos/{id}")
@ResponseBody
public String getFoosBySimplePathWithPathVariable(@PathVariable("id") long id) {
return "Get a specific Foo with id=" + id;
}

测试:curl http://localhost:8080/spring-mvc/foos/1
2 多个

@RequestMapping(value = "/foos/{fooid}/bar/{barid}")
@ResponseBody
public String getFoosBySimplePathWithPathVariables(@PathVariable long fooid, @PathVariable long barid) {
return "Get a specific Bar with id=" + barid + " from a Foo with id=" + fooid;
}

curl http://localhost:8080/spring-mvc/foos/1/bar/2

3 也支持正则表达式

@RequestMapping(value = "/bars/{numericId:[\\d]+}")
@ResponseBody
public String getBarsBySimplePathWithPathVariable(@PathVariable final long numericId) {
return "Get a specific Bar with id=" + numericId;
}

参数只接受数字

6) requestparam
http://localhost:8080/spring-mvc/bars?id=100

@RequestMapping(value = "/bars")
@ResponseBody
public String getBarBySimplePathWithRequestParam(@RequestParam("id") long id) {
return "Get a specific Bar with id=" + id;
}

@RequestMapping(value = "/bars", params = "id")
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParam(@RequestParam("id") long id) {
return "Get a specific Bar with id=" + id;
}

7) RequestMapping支持多个映射路径映射到同一个controller,如:

@RequestMapping(value = { "/advanced/bars", "/advanced/foos" })
@ResponseBody
public String getFoosOrBarsByPath() {
return "Advanced - Get some Foos or Bars";
}

curl -i http://localhost:8080/spring-mvc/advanced/foos
curl -i http://localhost:8080/spring-mvc/advanced/bars

甚至还支持put,post同时请求,如:
@RequestMapping(value = "/foos/multiple", method = { RequestMethod.PUT, RequestMethod.POST })
@ResponseBody
public String putAndPostFoos() {
return "Advanced - PUT and POST within single method";
}

5)autodetect:通过bean 类的自省机制(introspection)来决定是使用constructor 还是byType 方式进行自动装配。如果发现默认的
构造器,那么将使用byType 方式。

<bean id="bean1" class="cn.csdn.service.Bean1"
scope="singleton" autowire="autodetect"/>

5.scope:指定该Bean 的生存范围
scope用来声明IOC容器中的对象应该处的限定场景或者说该对象的存活空间,即在IOC容器在对象进入相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。
1) singleton类型的bean定义,在一个容器中只存在一个实例,所有对该类型bean的依赖都引用这一单一实例
2) scope为prototype的bean,容器在接受到该类型的对象的请求的时候,会每次都重新生成一 个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有 当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁
3) request ,session和global session
这三个类型是spring2.0之后新增的,他们只适用于web程序,通常是和XmlWebApplicationContext共同使用
request:

<bean id ="requestPrecessor" class="...RequestPrecessor"   scope="request" />

Spring容器,即XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,,该对象的生命周期即告结束
session

<bean id ="userPreferences" class="...UserPreferences"   scope="session" />

Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,他比request scope的bean会存活更长的时间,其他的方面真是没什么区别。
global session:

<bean id ="userPreferences" class="...UserPreferences"   scope="globalsession" /> 

global session只有应用在基于porlet的web应用程序中才有意义,他映射到porlet的global范围的session,如果普通的servlet的web 应用中使用了这个scope,容器会把它作为普通的session的scope对待。
6.init-method:指定该Bean 的初始化方法。destroy-method:指定该Bean 的销毁方法。这个就像servlet中init和destroy方法一样,只不过这里在配置文件配置的
7.abstract:指定该Bean 是否为抽象的。如果是抽象的,则
spring 不为它创建实例。
8.parent
如果两个Bean 的属性装配信息很相似,那么可以利用继
承来减少重复的配置工作。
装配Bean 的继承父类作为模板,不需要实例化,设置abstract=”true”

 <bean id=”parent” class=”cn.csdn.service.Parent”
abstract=”true”>

<property name=”name” value=”z_xiaofei168”/>
<property name=”pass” value=”z_xiaofei168”/>
</bean>

装配Bean 的继承
子类中用parent 属性指定父类标识或别名
子类可以覆盖父类的属性装配,也可以新增自己的属性装配

<bean id=”child” class=”cn.csdn.service.Chlid”
parent=”parent”>

<property name=”pass” value=”123123”/>
<property name=”age” value=”22”/>
</bean>