Spring的基本用法

Spring的基本用法

一、Spring bean的3中创建方法

    在大多数情况下,Spring容器直接通过new关键字调用构造器来创建Bean实例,而class属性指定Bean实例的实现类,但这不是实例化Bean的唯一方法。实际上,Spring支持使用以下三种方式来创建Bean:

(1)调用构造器创建Bean

    通过构造函数创建Bean,我们需要提供无参数构造函数,另外我们定义了一个name属性,并提供了setter方法,Spring容器通过该方法为name属性注入参数。

<?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="person" class="com.mao.gouzao.Person">  
      <!-- 通过调用setName方法,将VipMao作为参数传入 -->  
      <property name="name" value="VipMao"></property>  
    </bean>  
</beans>

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

    静态工厂是一个Java类,那么该class属性指定的就是该工厂的实现类,而不再是Bean的实现类,告诉Spring这个Bean应该由哪个静态工厂创建,另外我们还需要添加factory-method属性来指定由工厂的哪个方法来创建Bean实例,因此使用静态工厂方法创建Bean实例需要为<bean/>元素指定如下属性:

class:指定静态工厂的实现类,告诉Spring该Bean实例应该由哪个静态工厂创建(指定工厂地址)
factory-method:指定由静态工厂的哪个方法创建该Bean实例(指定由工厂的哪个车间创建Bean)
如果静态工厂方法需要参数,则使用<constructor-arg.../>元素传入

<?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">  
        <!-- 定义chinese Bean 由PersonFactory工厂的getPerson方法创建 -->  
    <bean id="chinese" class="com.mao.staticFactory.PersonFactory" factory-method="getPerson">  
      <!-- 为静态工厂的getPerson()方法传参 -->  
      <constructor-arg value="chinese"/>  
      <!-- 调用setMsg()方法为msg属性注入参数值 -->  
      <property name="msg" value="我是中国人"/>  
    </bean>     
    <!-- 创建american Bean -->  
    <bean id="american" class="com.mao.staticFactory.PersonFactory" factory-method="getPerson">  
      <constructor-arg value="american"/>  
      <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.mao.instanceFactory.PersonFactory"/>  
    <!-- 由实例工厂Bean的getPerson()方法,创建Chinese Bean, -->  
    <bean id="ch" factory-bean="personFactory" factory-method="getPerson">  
      <!-- 为该方法传入参数为chinese -->  
      <constructor-arg value="chinese"/>  
    </bean>  
    <!-- 由实例工厂Bean的getPerson()方法,创建American Bean, -->  
    <bean id="usa" factory-bean="personFactory" factory-method="getPerson">  
      <constructor-arg value="american"></constructor-arg>  
    </bean>  
</beans>
参考网址:http://blog.csdn.net/vipmao/article/details/51584571

二、Spring bean的作用域

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

(1)singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。这也是默认的作用域

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

(3)request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效

(4)session:对于每次HTTPSession,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

(5)globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

    其中比较常用的是singleton和prototype两种作用域。对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。

    eg:   <bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

1、创建对象的时机

   (1)在默认的情况下,在spring容器启动的时候创建对象

        在spring配置文件中,只要根据以上的三种方式的其中一种配置了,spring容器就会创建对象

        好处:spring容器和web容器整合的时候,当web容器启动的时候就可以初始化spring容器了,如果这个时候spring容器内

              部有错误,则直接会报错

        坏处:如果该bean中存放着大量的数据,而且数据的初始化发生在创建对象的时候,这个时候,数据会过早的驻留在内存

              中

   (2)如果在spring的配置文件中一个bean的配置中有lazy-init="true",那么该bean在调用getBean方法时创建对象

        坏处:不能过早的发现错误

        好处:按照需求加载数据(什么时候要什么时候加载)

2、Spring bean init方法和destroy方法

   <bean id="stage" class="com.spring.test.initdesotry.Stage"scope="prototype" //注意这句话,如果是singleton或者没有该句(默认情况)时,才会执行destroy-method指定的方法,如果是当前的prototype不会触发destroymethod的执行

   init-method="turnOnLight"

   destroy-method="turnOffLight"/>

三、Spring 属性的装配

(1)Set注入

   这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口)

public class SpringAction {  
        //注入对象springDao  
    private SpringDao springDao;  
        //一定要写被注入对象的set方法  
        public void setSpringDao(SpringDao springDao) {  
        this.springDao = springDao;  
    }  
  
        public void ok(){  
        springDao.ok();  
    }  
}
<!--配置bean,配置后该类由spring管理-->  
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
            <!--(1)依赖注入,配置当前类中相应的属性-->  
            <property name="springDao" ref="springDao"></property>  
        </bean>  
    <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

(2)构造器注入
   这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:

public class SpringAction {  
    //注入对象springDao  
    private SpringDao springDao;  
    private User user;  
      
    public SpringAction(SpringDao springDao,User user){  
        this.springDao = springDao;  
        this.user = user;  
        System.out.println("构造方法调用springDao和user");  
    }  
          
        public void save(){  
        user.setName("卡卡");  
        springDao.save(user);  
    }  
}
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
            <constructor-arg index="0" ref="springDao"></constructor-arg>  
            <constructor-arg index="1" ref="user"></constructor-arg>  
</bean> 

(3)基于注解的属性装配

    在配置文件中打开<context:annotation-config>节点,告诉Spring容器可以用注解的方式注入依赖对象;其在配置文件中的代码如下:

     <context:annotation-config></context:annotation-config>

在配置文件中配置bean对象,如下:

    <bean id="userDao" class="com.springtest.dao.impl.UserDAOImpl"></bean>

    <bean id="userBiz"class="com.springtest.biz.impl.UserBizImpl"></bean>

在需要依赖注入的BIZ类中,声明一个依赖对象,不用生成该依赖对象的setter方法,并且为该对象添加注解

public class UserBizImpl implements UserBiz {
   @Resource(name="userDao")
   private UserDAO userDao = null;
   public void addUser() {
      this.userDao.addUser();
   }
}

   其中,在Java代码中可以使用@Autowired或@Resource注解方式进行Spring的依赖注入。两者的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配

  比如:我们用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与UserDAO对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;

  如果用@Resource进行依赖注入,它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型,例 如:@Resource(name="userDao"),如果没有找到该名称,则会按照类型去寻找,找到之后,会对字段userDao进行注入。通常我们使用@Resource。

常用的注解:

@Configuration 将一个类定义为Bean的配置类

  @Componet("userDao")  通过Repository定义一个DAO的bean

                       等价于<beanid="userDao" class="com.ib.anno.UserDao"/>

  @Repository            用户对DAO实现类进行注解

  @Service               用户对Service实现类进行注解

  @Controller            用户对Controller实现类进行注解

 

  @Autowired             默认按类型匹配注入Bean,自动注入,默认情况下required为ture,要求一顶耀找到匹配的Bean,否

                           则报NoSuchBeanDefinitionException

  @Autowired(required=false)  容器中没有一个标注变量类型匹配的Bean,忽略NoSuchBeanDefinitionException异常

  @Qualifier("userDao")  指定注入userDao Bean的名称(如果一个方法拥有多个入参,在默认情况下Spring自动选择匹配入参

                            类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称)

                            以下两个注解和@Autowired注解的功能类似,除非必要都使用@Autowired注解

  @Resource("userDao")   按名称匹配注入Bean,要求提供一个Bean名称的属性,如果属性为空,则自动采用标注处的变量名

                            或方法名作为Bean 的名称

    @Inject                按类型匹配注入Bean,没有required属性

 

  @PostConstruct         相当于bean的init-method属性的功能 

  @PreDestroy            相当于bean的destroy-method属性的功能

四、Spring bean集合类的注入

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Properties;

public class MoonlightPoet {
    private String name;
    private int age;
    private Poem poem;
    private List<String> list;
    private Map<String, String> map;
    private Properties properties;
    public void perform() {
        System.out.println("name : " + name);
        System.out.println("age : " + age);
        poem.recite();
        for (String val : list) 
            System.out.println("in list : " + val);
        for (Entry<String, String> entry : map.entrySet())
            System.out.println("in map : " + entry.getKey() + " -- " + entry.getValue());
        for (Entry<Object, Object> entry : properties.entrySet())
            System.out.println("in properties : " + entry.getKey() + " -- " + entry.getValue());
    }
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "spring-idol.xml");
        MoonlightPoet moonlightPoet = (MoonlightPoet) context.getBean("moonlightPoet");
        moonlightPoet.perform();
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Poem getPoem() {
        return poem;
    }
    public void setPoem(Poem poem) {
        this.poem = poem;
    }
    public List<String> getList() {
        return list;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public Map<String, String> getMap() {
        return map;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    public Properties getProperties() {
        return properties;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<bean id="moonlightPoet" class="com.moonlit.myspring.MoonlightPoet">
    <property name="name" value="moonlit" />
    <property name="age" value="22" />
    <property name="poem" ref="sonnet29" />
    <property name="list">
      <list>
        <value>hello</value>
        <value>world</value>
        <!-- if bean, use <ref bean="XX"> -->
      </list>
    </property>
    <property name="map">
      <map>
        <entry key="key1" value="value1" />
        <entry key="key2" value="value2" />
        <entry key="key3" value="value3" />
      </map>
    </property>
    <property name="properties">
      <props>
        <prop key="GUITAR">STRUM STRUM STRUM</prop>
        <prop key="CYMBAL">CRASH CRASH CRASH</prop>
          <prop key="HARMONICA">HUM HUM HUM</prop>
      </props>
    </property>
  </bean>

五、Spring自动扫描和管理Bean

    我们都是使用XML的bean定义来配置组件。在一个稍大的项目中,通常会有上百个组件,如果这些组件采用XML的bean定义来配置,显然会增加配置文件的体积,查找及维护起来也不太方便。Spring2.5为我们引入了组件自动扫描机制,它可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进Spring容器中管理。它的作用和在XML文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息:

<?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-4.2.xsd">

    <context:component-scan base-package="cn.itcast" />

</beans>
   其中<context:component-scanbase-package="cn.itcast" />这个配置隐式注册了多个对注解进行解析处理的处理器,包括<context:annotation-config/>该配置注册的处理器,也就是说写了<context:component-scanbase-package="cn.itcast" />配置,就不用写<context:annotation-config/>配置了,此外base-package为需要扫描的包(含子包)。
@Service用于标注业务层组件、 @Controller用于标注控制层组件(如Struts2中的action)、@Repository用于标注数据访问组件,即DAO组件。而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
本文是建立在@Autowire注解与自动装配的案例基础上的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值