spring知识点分析之bean

在spring中,不再需要通过传统的方式创建,而是根据注解或者xml将类直接解析成bean,本文讲讲解关于bean的一些知识点。

一、bean的定义

Spring容器集中管理Bean的实例化,Bean实例可以通过BeanFactory的getBean(String  beanid)方法得到。BeanFactory是一个工厂,程序只需要获取BeanFactory引用,即可获得Spring容器管理全部实例的引用。程序不需要与具体实例的实现过程耦合。大部分Java EE应用里,应用在启动时,会自动创建Spring容器,组件之间直接以依赖注入的方式耦合,甚至无须主动访问Spring容器本身。

1.基于xml的半定义(需要定义setter方法)

   元素是Spring配置文件的根元素,元素可以包含多个子元素,每个

   素可以定义 一个Bean实例,每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性。

   Id:确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成。Bean的id属性

         在Spring容器中是唯一的。

   Class:指定该Bean的具体实现类。注意这里不能使接口。通常情况下,Spring会直接使用new关键字创建该Bean的实

               例,因此,这里必须提供Bean实现类的类名。

   当我们在配置文件中通过方法配置一个Bean时,这样就需要该Bean实现

   类中必须有 一个无参构造器。

   示例:

  在applicationContext.xml中配置bean信息

2.基于注解的bean定义(不需要提供setter方法)

   Spring为此提供了四个注解,这些注解的作用与上面的XML定义bean效果一致,在于将组件交给Spring容器管理。

   组件的名称默认是类名(首字母变小写),也可以自己修改:
  @Component:当对组件的层次难以定位的时候使用这个注解
  @Controller:表示控制层的组件
  @Service:表示业务逻辑层的组件
  @Repository:表示数据访问层的组件
   示例:

   注解定义bean

//不知道该组件属于什么层次时,可以直接使用该注解@Component
@Component("address")
public class Address{
    
    private Integer id;

    //对于非bean id时的注入直接用@Value赋值
    @Value("湖北省黄石市阳新县黄双口镇金星村")
    private String name;

    public String getName() {
        return name;
    }
 
}

//不知道该组件属于什么层次时,可以直接使用该注解@Component
@Component("user")
public class Teacher {
    
    //对于非bean id时的注入直接用@Value赋值
    @Value("25")
    private Integer age;

    //对于非bean id时的注入直接用@Value赋值
    @Value("石破天")
    private String name;
    
    //对于bean id类型使用@Resource注解进行注入
    @Resource
    private Address address;
 
    public Integer getAge() {
        return name;
    }

    public String getName() {
        return name;
    }
 
}

  applicationContext.xml 中添加一下配置信息。


3.基于Java类的bean定义(需要提供setter方法)


@Configuration
public class BeansConfiguration {
 
    @Bean
    public Student student(){
        Student student=new Student();
        student.setName("张三");
        student.setTeacher(teacher());
        return student;
    }
 
    @Bean
    public Teacher teacher(){
        Teacher teacher=new Teacher();
        teacher.setName("李四");
        return teacher;
    }
 
}

二、bean的作用域

       当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。   

   Spring支持5种作用域:

       Singleton:单例模式。在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例,这是默认的配置。

       Prototype:原型模式。每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实

                          例。

       request:对于每次HTTP请求,使用request定义的Bean都将产生一个新的实例,即每次HTTP请求都会产生不同

                      的Bean实例。当然只有在WEB应用中使用Spring时,该作用域才真正有效。

       session:对于每次HTTPSession,使用session定义的Bean都将产生一个新的实例时,即每次HTTP Session都将

                      产生不同的Bean实例。同HTTP一样,只有在WEB应用才会有效。

        global session:每个全局的HTTPSession对应一个Bean实例。仅在portlet Context的时候才有效。

                                  比较常用的singleton和prototype。如果一个Bean实例被设置为singleton,那么每次请求该

                                  Bean 时都会获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命

                                  周期行为。如果一个Bean实例被设置为prototype,那么每次请求该di的Bean,Spring都会

                                  创建一个新的Bean实例返回给程序,在这种情况下,Spring容器仅仅使用new关键字创建

                                  Bean实例,一旦创建成功,容器将不会再跟踪实例,也不会维护Bean实例的状态。

      如果我们不指定Bean的作用域,则Spring会默认使用singleton作用域。设置Bean的作用域是通过scope属性来指

       定。 可以接受Singleton、prototype、request、session、global session 5个值。

 

三、bean的创建

Spring支持如下三种方式创建Bean

1:调用构造器创建Bean

         调用构造方法创建Bean是最常用的一种情况Spring容器通过new关键字调用构造器来创建Bean实例,通过class

         属性指定Bean实例的实现类,也就是说,如果使用构造器创建Bean方法,则元素必须指定class属性,

         其实Spring容器也就是相当于通过实现类new了一个Bean实例。调用构造方法创建Bean实例,通过名字也可以

         看出,我们需要为该Bean类提供无参数的构造器。

        因为是通过构造函数创建Bean,因此我们需要提供无参数构造函数,另外我们定义了一个name属性,并提供了

        setter方法,Spring容器通过该方法为name属性注入参数。

         示例:(以xml形式定义bean)

package com.spring;

public class User implements IUser {
	private String name;
	private Integer age;

        public User(){
    
        System.out.println("通过spring会通过new关键字调用无参构造器实例化");
        }
	//提供setter方法,在xml中定义bean时,将调用该方法给对应的属性赋值即所谓的依赖注入
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

  applicationContext.xml

  
      

        
          
        
          
            
           
          
      

  2:调用静态工厂方法创建Bean

        通过静态工厂创建Bean是把创建Bean的任务交给了静态工厂,而不是

        构造函数,这个静态工厂就是一个Java类,在使用静态工厂创建Bean需要在元素内添加class属性,

        静态工厂是一个Java类,那么该class属性指定的就是该工厂的实现类,而不再是Bean的实现类,告诉Spring

        这个Bean应该由哪个静态工厂创建,另外我们还需要添加factory-method属性来指定由工厂的哪个方法来创建

        Bean实例,因此使用静态工厂方法创建Bean实例需要为元素指定如下属性:

        class:指定静态工厂的实现类,告诉Spring该Bean实例应该由哪个静态工厂创建(指定工厂地址)

       factory-method:指定由静态工厂的哪个方法创建该Bean实例(指定由工厂的哪个车间创建Bean)

        如果静态工厂方法需要参数,则使用元素传入

       示例:

 步骤: 1.定义一个接口 Person
       2.定一个实现Person接口的实现类HuBeiMan
       3.定义另外一个实现Person接口的实现类ShenZenMan
       4.定义一个静态工厂,主要是用来创建实体类
       5.xml定义bean(创建bean实例,实际实例由静态工厂创建)

1
public interface Person{

   public void say();
}

2
public class HuBeiMan implements Person{


    private String msg;  
    //提供setter方法  
    public void setMsg(String msg)   
    {  
        this.msg = msg;  
    }  

    @Override
    public void say(){
        System.out.println("湖北人说的方言很难懂");
    }

}


public class ShenZenMan implements Person{


    private String msg;  
    //提供setter方法  
    public void setMsg(String msg)   
    {  
        this.msg = msg;  
    }  

    @Override
    public void say(){
        System.out.println("深圳人大部分来自全国各地");
    }

}
 3
 //在xml中定义bean时,需要创建什么类的bean实例,可以class直接指向静态工厂类
 public class PersonFactory {  
    //调用对应方法,并传递对应参数
    public static Person getPerson(String arg)  {
       
       根据指定name来获取对应的实例,该name在xml中
       if(arg.equalsIgnoreCase("chinese"))  
       {  
        return new Chinese();  
       }     
    else  
    {  
        return new American();  
    }  
  }  
}  

4
  
      

          
          
            
               
 
               
               
            
 
          
          
            

            
             
     

3:调用实例工厂方法创建Bean

 静态工厂通过class指定静态工厂实现类然后通过相应的方法创建即可,调用实例工厂则需要先创建该工厂的Bean

 实例,然后引用该实例工厂Bean的id创建其他Bean,在实例工厂中通过factory-bean指定工厂Bean的实例,在调

 用实例化工厂方法中,不用在中指定class属性,因为这时,咱们不用直接实例化该Bean,而是通过调用

 实例化工厂的方法,创建Bean实例。调用实例化工厂需要为指定一下两个属性:

               factory-bean :该属性指定工厂Bean的id

               factory-method:该属性指定实例工厂的工厂方法。

示例:在上一种方法示例的基础上修改对应的配置文件


      
     
 
          
         
 
          
          
                 
                 
          

          
          
            
          
      

实例工厂创建Bean和调用静态工厂的区别

调用实例工厂将工厂单独拿了出来(先实例化工厂)创建一个工厂Bean,通过工厂的class属性指定工厂的

实现类,然后再需要创建其他Bean时,只需要在该元素添加factory-bean、factory-method指定该Bean

是有哪个实例工厂的哪个方法创建就可以了,放在现实生活中就是:我们先找一个地方创建一个工厂,id指定工

厂注册名字(xxx有限公司),class指定公司所在地,工厂里面有车间(创造其他Bean的方法),那好有了工厂

我们再需要创建其他Bean时,只需要指定这个Bean是由,哪个工厂的哪个车间创建的即可,也就是只需要在该

元素添加factory-bean、factory-method属性即可。

 

四、bean的注入

1 注入bean

在Spring中,注入依赖对象可以采用手工装配或自动装配,一般是使用手工注入,因为自动装配容易出现未知问题,

自动装配是在配置文件中实现的,不用再配置文件中写,但是在类中还是要生成依赖对象的setter方法,

如下:

       只需要配置一个autowire属性即可完成自动装配

       autowire属性值有:

                   no:默认的。默认为不自动装配

                   byName:根据属性名称自动进行查找与该name相同的bean并装配,如果没有找到,则属性值为null

                   byType:根据属性类型自动进行装配,如有多个会报异常,如果没有找到,则属性值为null

以下三种方式都属于手工装配。

1.1 setter属性注入

 ①ref标识符





      





   
      
      
   





   
   


 ② value



      
      


或者


      
      
         湖北省黄石市阳新县黄双口镇金星村

 1.2 使用构造器注入

       示例:

       第一步:定义的类符合以下要求

public class User{
  
  //声明依赖对象
  private  Address address= null;

  //生成无参构造函数
  public User(){
    super;
  }
  
  //生成有参构造函数
  public User(Address address){
    super;
    this.address=address;
  }
}

     第二步:在配置文件中配置该类的bean,并配置构造器,关键元素节点  ,该节点有四个属

                   性:        

                  index是索引,指定注入的属性,从0开始,如:0代表personDao,1代表str属性;

                  type是指该属性所对应的类型,如Persondao对应的是com.aptech.dao.PersonDAO;

                 ref 是指引用的依赖对象;

                 value 当注入的不是依赖对象,而是基本数据类型时,就用value;













1.3 使用注解注入

 在类的内部定义依赖属性上加上注解,并在配置文件中加上

 信息,该配置信息配置隐式的注册了多个对注释进行解析的处理器:器AutowiredAnnotationBeanPostProcessor、
 CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。

       注解:

           @Resource:默认按类型装配

                                 用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与

                                 UserDao对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;

           @Autowired:它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型。

                               例如:@Resource(name="userDao"),如果没有找到该名称,则会按照类型去寻找,找到之后,

                              会对字段userDao进行注入。

        示例:

        第一步:在依赖属性上加上注解

//不需要setter方法
public class UserServiceImpl implements UserService {
    
    @Resource(name="userDao")   //或者@AutoWired

    private UserDAO userDao = null;

    public void addUser() {

         this.userDao.addUser();

    }

}

   第二步:bean的定义(有三种,这里以xml定义为例)  



  第四步:在applicationContext.xml中加上 

2 集合注入

   2.1 list


   
        
          
          
          1
          2
          3
          
        
    

2.2 map


        
            
            
                
                    value1
                
                
                    key2
                
            
        
    

2.3 props




value1
value2


2.4 set


   < property  name ="interest" >    
             <!--注入时调用的setter方法的参数类型为Set类型时-->
             < set >    
                 < value > 唱歌     
                 < value > 跳舞     
                 < value > 书法     
                 
    

 

你可能感兴趣的:(spring,j2EE,web)