spring知识点分析之bean

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

一、bean的定义

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

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

   <beans…/>元素是Spring配置文件的根元素,<beans…/>元素可以包含多个<bean…/>子元素,每个<bean…/>元

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

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

         在Spring容器中是唯一的。

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

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

   当我们在配置文件中通过<bean id=”xxxx” class=”xx.XxClass”/>方法配置一个Bean时,这样就需要该Bean实现

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

   示例:

  在applicationContext.xml中配置bean信息

<bean name="userDao" class="com.spring.User"></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 中添加一下配置信息。

<!--扫描组件的包目录-->
<context:component-scan base-package="entity"/>

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方法,则<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

<?xml version="1.0" encoding="GBK"?>  
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns="http://www.springframework.org/schema/beans"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">  

        
        <!-- 指定class属性,通过构造方法创建Bean实例 -->  
        <!--通过<bean>元素的id属性指定该bean的唯一名称,class属性指定该bean的实现类,可以理解成
         Spring容器就是通过该实现类new了一个Bean-->
        <bean id="user" class="com.spring.usermanage.entity.User">  
          <!-- 通过<constructor-arg>标签的name属性和value属性指定了:构造方法赋值 -->  
         <constructor-arg name="name" value="魔术师"></constructor-arg>  
        </bean>  
    </beans>  

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

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

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

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

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

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

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

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

        如果静态工厂方法需要参数,则使用<constructor-arg.../>元素传入

       示例:

 步骤: 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
<?xml version="1.0" encoding="GBK"?>  
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns="http://www.springframework.org/schema/beans"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">  

        <!-- 定义HuBeiMan Bean 由PersonFactory工厂的getPerson方法创建 -->  
        <bean id="HuBeiMan" class="com.spring.PersonFactory" factory-method="getPerson">  
          <!-- 为静态工厂的getPerson()方法传参 -->  
             <constructor-arg value="HuBeiMan"/>  
 
             <!-- 调用setMsg()方法为msg属性注入参数值 -->  
             <property name="msg" value="我是中国人"/>  
        </bean>    
 
        <!-- 创建ShenZenMan Bean -->  
        <bean id="ShenZenMan" class="com.spring.PersonFactory" factory-method="getPerson">  
          <constructor-arg value="ShenZenMan"/>  

          <property name="msg" value="我是深圳人"></property>  
           </bean>  
   </beans>  

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

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

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

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

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

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

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

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


    <?xml version="1.0" encoding="GBK"?>  
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns="http://www.springframework.org/schema/beans"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> 
 
        <!-- 配置工厂Bean,class指定该工厂的实现类,该Bean负责产生其他Bean实例 -->  
        <bean id="personFactory" class="com.spring.PersonFactory"/> 
 
        <!-- 由实例工厂Bean的getPerson()方法,创建HuBeiMan Bean, -->  
        <bean id="HuBeiMan" factory-bean="personFactory" factory-method="getPerson">  
               <!-- 为该方法传入参数为HuBeiMan-->  
               <constructor-arg value="HuBeiMan"/>  
        </bean>  

        <!-- 由实例工厂Bean的getPerson()方法,创建ShenZen Bean, -->  
        <bean id="ShenZen" factory-bean="personFactory" factory-method="getPerson">  
          <constructor-arg value="ShenZen"></constructor-arg>  
        </bean>  
    </beans>  

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

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

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

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

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

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

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

 

四、bean的注入

1 注入bean

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

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

如下:

       <bean id="***" class="***" autowire="byType"> 只需要配置一个autowire属性即可完成自动装配

       autowire属性值有:

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

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

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

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

1.1 setter属性注入

 ①ref标识符


<!--通过ref来注入有两种形式-->

<bean id="address" class="com.spring.Address">
      <property name="content"  value="湖北省黄石市阳新县黄双口镇金星村">
</bean>

<!--1:单独添加ref元素-->
<bean id="user" class="com.spring.User">

   <property name="address">
      <!--其他的bean的id-->
      <ref bean="address"/>
   </property>
</bean>

<!--2:property元素中的ref属性-->
<bean id="user" class="com.spring.User">

   <property name="address" ref="address">
   </property>
</bean>

 ② value


<bean id="address" class="com.spring.Address">
      <!--注入属性非符合类型,即不是bean id时,直接用value进行赋值-->
      <property name="content"  value="湖北省黄石市阳新县黄双口镇金星村">
</bean>

或者

<bean id="address" class="com.spring.Address">
      <!--注入属性非符合类型,即不是bean id时,直接用value进行赋值-->
      <property name="content">
         <value>湖北省黄石市阳新县黄双口镇金星村</value>
</bean>

 1.2 使用构造器注入

       示例:

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

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

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

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

                   性:        

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

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

                 ref 是指引用的依赖对象;

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

<!-- 利用构造器配置依赖注入 -->
<!--userDao bean实例-->
<bean id="userDao" class="com.spring.UserDaoImpl"></bean>

<!--service bean实例-->
<bean id="service" class="com.spring.ServiceImpl">

<!--调用service的有参构造函数将userDao作为第一个type为UserDao的bean注入到service bean中-->
<constructorarg index="0" type="com.spring.UserDao" ref="userDao"></constructor-arg>
<!--非bean id直接赋值,不需要指定type-->
<constructor-arg index="1" value="石破天"></constructor-arg>

</bean>

1.3 使用注解注入

 在类的内部定义依赖属性上加上注解,并在配置文件中加上<context:annotation-config></context:annotation-config>

 信息,该配置信息配置隐式的注册了多个对注释进行解析的处理器:器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定义为例)  

<bean id="userDao" class="com.spring.UserDaoImpl"></bean>

<bean id="userService" class="com.spring.UserServiceImpl"></bean>

  第四步:在applicationContext.xml中加上  <context:annotation-config></context:annotation-config>

2 集合注入

   2.1 list

<bean id="test" class="com.spring.test">
   
        <property name="lists">
          <!--注入时调用的setter方法的参数类型为List类型时-->
          <list>
          <value>1</value>
          <value>2</value>
          <value>3</value>
          </list>
        </property>
    </bean>

2.2 map

<bean id="test" class="com.spring.test">
        <property name="map">
            <!--注入时调用的setter方法的参数类型为Map类型时-->
            <map>
                <entry key="key1">
                    <value>value1</value>
                </entry>
                <entry key="key2">
                    <value>key2</value>
                </entry>
            </map>
        </property>
    </bean>

2.3 props

<bean id="test" class="com.spring.test">
<property name="props">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
</property>
</bean>

2.4 set

<bean id="test" class="com.pring.Test">
   < property  name ="interest" >    
             <!--注入时调用的setter方法的参数类型为Set类型时-->
             < set >    
                 < value > 唱歌 </ value >    
                 < value > 跳舞 </ value >    
                 < value > 书法 </ value >    
             </ set >    
    </ property >
</bean>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值