码迷,mamicode.com
首页 > 编程语言 > 详细

【Spring】IOC之基于注解的配置bean(下)

时间:2015-04-16 19:54:07      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:spring   注释   

  林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

一、@Autowired注解

       Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。Spring 通过一个 BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。 在applicatonContext.xml中 把原来 引用的<porpery >标签去掉。

     @Autowired默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:

      @Autowired() 
      @Qualifier("baseDao")
      private BaseDao baseDao;
1)对集合进行注解

       @Autowired(required=false)
       private List<User> userList;
2)对方法进行注解

     @Autowired
     @Qualifier("user1")
     public void add(User user){
	System.out.println(user);
      }

     @Autowired
     public void setUserDao(UserDao userDao) {//用于属性的setter方法上
     this.userDao= userDao;
}
3)对构造函数进行注解

@Autowired 
public Boss(Car car ,Office office){ 
this.car = car;
this.office = office  
}  

4)对字段进行注解

	@Autowired
	private UserDao userDao;

        在默认情况下使用@Autowired注释进行自动注入时,Spring容器中匹配的候选Bean数目必须有且仅有一个。当找不到一个匹配的Bean时,Spring容器将抛出BeanCreationException异常,并指出必须至少拥有一个匹配的Bean。当不能确定Spring容器中一定拥有某个类的Bean时,可以在需要自动注入该类Bean的地方可以使用@Autowired(required=false),这等于告诉Spring:在找不到匹配Bean时也不报错。
         当然,一般情况下,使用@Autowired的地方都是需要注入Bean的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动Spring容器,仅引入一些模块的Spring配置文件),所以@Autowired(required=false)会很少用到。
和找不到一个类型匹配Bean相反的一个错误是:如果Spring容器中拥有多个候选Bean,Spring容器在启动时也会抛出BeanCreationException异常。



二、 @Qualifier注解

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

1). 可能存在多个UserDao实例

Java代码

  1. @Autowired       
  2. @Qualifier("userServiceImpl")         
  3. public IUserService userService;  

或者

Java代码

  1. @Autowired       
  2. public void setUserDao(@Qualifier("userDao") UserDao userDao) {        
  3.     this.userDao = userDao;        

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

2). 可能不存在UserDao实例

Java代码

  1. @Autowired(required = false)        
  2. public IUserService userService;    
        @Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

三、 @Resource注解


          JSR-250标准注解,推荐使用它来代替Spring专有的@Autowired注解。@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName自动注入罢了。@Resource有两个属性是比较重要的,分别是name和type,Spring将 @Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

1)字段上注解,byname

     @Resource(name="userDao")
     private UserDao userDao;
2)方法上注解

      @Resource
     public void setUserDao(UserDao userDao) {//用于属性的setter方法上
     this.userDao= userDao;
}
         @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方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;



四、@Resource与@Autowired使用区别

    @Resource(name="loginService")
    private LoginService loginService;
 
    @Autowired(required=false)@Qualifier("loginService")
    private LoginService loginService;
   (1).@Autowired 与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上;
   (2).@Autowired 默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设

    置它的required属性为false,如:@Autowired(required=false) .

如果我们想使用名称装配可以结合 @Qualifier注解进行使用;
    (3).@Resource(这个注解属于J2EE的),默认安装名称进行装配,名称可以通过name属性进行指定,如果没
    有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属
    性名进行装配。当找不到与名称匹配的bean时才按照类型进行装 配。但是需要注意的是,如果name属性一旦指
    定,就只会按照名称进行装配。

五、@Scope注解

在使用XML定义Bean时,我们可能还需要通过bean的scope属性来定义一个Bean的作用范围,我们同样可以通过@Scope注解来完成这项工作:

Java代码

@Scope("session")        
@Component()        
public class UserSessionBean implements Serializable{      
 ... ...     
} 
或者

@Repository("user")
@Scope("prototype")
//@Repository用于标注数据访问组件,即DAO组件
//@Scope("prototype")让其每次返回不同的实例,默认是单例
public class User {

六、 @PostConstruct(JSR-250)注解

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

七、@PreDestroy(JSR-250)注解

在方法上加上注解@PreDestroy,这个方法就会在Bean初始化之后被Spring容器执行。其用法同@PostConstruct。和@PostConstruct 区别

于:@PostConstruct注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。

@PostConstruct
	private void init1(){
		System.out.println("execute int init1");
	}
	@PostConstruct
	private void init2(){
		System.out.println("execute int init2");
	}
	@PreDestroy
	private void destory1(){
		System.out.println("execute int destory1");
	}
	@PreDestroy
	private void destory2(){
		System.out.println("execute int destory2");
	}

       Spring容器中的Bean是有生命周期的,Spring允许在Bean在初始化完成后以及Bean销毁前执行特定的操作,既可以通过实现InitializingBean/DisposableBean接口来定制初始化之后/销毁之前的操作方法,也可以通过<bean>元素的init-method/destroy-method属性指定初始化之后/销毁之前调用的操作方法。JSR-250为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct和@PreDestroy,这两个注释只能应用于方法上。标注了@PostConstruct注释的方法将在类实例化后调用,而标注了@PreDestroy 的方法将在类销毁之前调用。

八、使用范例

定义User.java

package com.mucfc.model;

public class User {
	String name;
	int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	public String toString(){
		return "name="+name+" id="+id;
	}
}

定义UserDao,java

package com.mucfc.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import com.mucfc.model.User;
@Component
public class UserDao {
	
@Autowired
@Qualifier("user1")
public void add(User user){
	System.out.println(user);
}
}
其中user1在beans.xml已经定义

然后就是:

package com.mucfc.service;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.mucfc.dao.UserDao;
import com.mucfc.model.User;

@Component
public class MyComponent {
	@Autowired(required=false)
	private List<User> userList;
	public List<User> getUserList() {
		return userList;
	}
	@PostConstruct
	private void init1(){
		System.out.println("execute int init1");
	}
	@PostConstruct
	private void init2(){
		System.out.println("execute int init2");
	}
	@PreDestroy
	private void destory1(){
		System.out.println("execute int destory1");
	}
	@PreDestroy
	private void destory2(){
		System.out.println("execute int destory2");
	}
}
另一个:

package com.mucfc.service;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.mucfc.dao.UserDao;
@Component("service")
public class MySerivce {
	@Resource(name="userDao")
	private UserDao userDao;
	public UserDao getUserDao() {
		return userDao;
	}
	
}

beans.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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="com.mucfc" />

     <bean id="user" class="com.mucfc.model.User" p:name="evankaka" p:id="0009"/> 
     <bean id="user1" class="com.mucfc.model.User" p:name="simle" p:id="456"/>
     

</beans>

最后就是测试的方法了:

package com.mucfc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mucfc.service.MyComponent;
import com.mucfc.service.MySerivce;

public class Test {

	public static void main(String[] args) {
		 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		 MySerivce service= context.getBean("service", MySerivce.class);
		 MyComponent myComponent=context.getBean("myComponent", MyComponent.class);
		 System.out.println("--------list--------");  
	        for (int i = 0; i < myComponent.getUserList().size(); i++) {  
	            System.out.println(myComponent.getUserList().get(i));  
	        }  
	        
	        System.out.println(service.getUserDao());  
	        ;
	        ((ClassPathXmlApplicationContext)context).destroy();
	}

}

输出结果

技术分享


  林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka


【Spring】IOC之基于注解的配置bean(下)

标签:spring   注释   

原文地址:http://blog.csdn.net/evankaka/article/details/45077041

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!