zoukankan      html  css  js  c++  java
  • Spring的学习(二、Spring中的Bean)

    Bean的配置

     

    Spring容器支持两种格式的配置文件,分别为properties文件格式和XML文件格式(常用),其中XML这种配置方式是通过XML文件来注册并管理Bean之间的依赖关系的。

    XML配置文件

    XML配置文件的根元素是<beans>,里面包含了多个<bean>子元素,每个<bean>定义了一个bean,并描述了该Bean如何被装配到Spring容器中。

    <bean>元素中的属性

    (1)id:一个Bean的唯一标识符,Spring容器对Bean的配置、管理都通过该属性来完成。

    (2)name:Spring容器对Bean的配置、管理也都可以通过该属性来完成。可以有多个name,中间用逗号或者分号隔开。一般想要给Bean添加别名或想要使用一些不合法的XML字符,如:/,就可以通过name属性进行设置。

    (3)class:该属性指定了Bean的具体实现类,它必须是一个完整的类名,使用类的全限定名。

    (4)scope:用来设定Bean实例的作用域,其属性值有singleton(单例)、prototype(原型)、request、session和global Session。默认为singleton。

    (5)constructor-arg:bean元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的index属性指定构造参数的序号(从0开始),type属性指定构造参数的类型,其参数值可以通过ref属性或者value属性直接指定,也可以通过ref或value元素指定。

    (6)property:bean元素的子元素,用于调用Bean实例中的Setter方法完成属性赋值,从而完成依赖注入。该元素的name属性指定Bean实例中的相应属性名,属性值可通过ref或value属性直接指定。

    (7)ref:property、constructor-arg等元素的子元素,该元素中的bean属性用于指定对Bean工厂中某个Bean实例的引用。

    (8)value:property、constructor-arg等元素的子元素,用来直接指定一个常量值。

    (9)list:用于封装List或数组类型的依赖注入。

    (10)set:用于封装Set类型属性的依赖注入。

    (11)map:用于封装Map类型属性的依赖注入。

    (12)entry:map元素的子元素,用于设置一个键值对。其key属性指定字符串类型的键值,ref或value子元素指定其值。

    注意:如果在Bean中未指定id和name,则Spring会将class值当作id使用。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--使用id属性定义bean1,其对应的实现类为com.tm.bean.bean1 -->
        <bean id="bean1" class="com.tm.bean.bean1" />
        <!--使用name属性定义bean2,其对应的实现类为com.tm.bean.bean2-->
        <bean name="bean2" class="com.tm.bean.bean2" />
    </beans>

    Bean的实例化

     

    Spring中,实例化Bean有三种方式:构造器实例化、静态工厂方式实例化、实例工厂方式实例化。

    1. 构造器实例化

    构造器实例化是指Spring容器通过Bean对应的类中默认的构造函数来实例化Bean。

    beans1.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--使用id属性定义bean1,其对应的实现类为com.tm.bean.Bean1 -->
        <bean id="bean1" class="com.tm.bean.Bean1" />
    </beans>

    Bean1.java

    package cn.tm.bean
    
    public class Bean1{
        
    }

    测试类

    public class test(){
        @Test
        public void test(){
            //这里要填写xml对应的配置文件的路径。在加载时,Spring容器会通bean1的实现类Bean1中的默认无参构造函数对Bean进行实例化
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans1.xml);
            System.out.println(applicationContext.getBean("bean1"));
        }
    }

    2. 静态工厂方式实例化

    该方式要求自己创建一个静态工厂的方法来创建Bean的实例。

    beans2.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--使用id属性定义bean2,通过class属性指定其对应的工厂实现类为MyBean2Factory,factory-method属性指定方法名 -->
        <bean id="bean2" class="com.tm.bean.MyBean2Factory" factory-method="createBean" />
    </beans>

    Bean2.java

    package cn.tm.bean;
    
    public class Bean2{
        
    }

    MyBean2Factory.java

    package cn.tm.bean;
    
    public class MyBean2Factory{
        //使用自己的工厂创建bean实例
        public static Bean2 createBean(){
            return new Bean2();
        }
    }

    测试类

    public class test(){
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans2.xml);
            System.out.println(applicationContext.getBean("bean2"));
        }
    }

    3. 实例工厂方式实例化

    该种方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向其实例化的类,而是通过factory-bean属性配置一个实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。

    beans3.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 配置工厂 -->
        <bean id="MyBean3Factory" class="com.tm.bean.MyBean3Factory"/>
        <!-- 使用factory-bean属性配置一个实例工厂,使用factory-method属性确定使用工厂中的哪个方法 -->
        <bean id="bean3" factory-bean="MyBean3Factory" factory-method="createBean"></bean>
    </beans>

    Bean3.java

    package cn.tm.bean;
    
    public class Bean3{
        
    }

    MyBean3Factory.java

    package cn.tm.bean;
    
    public class MyBean3Factory{
        //默认的无参构造方法
        public MyBean3Factory(){
            System.out.println("bean3工厂实例化中");
        }
        //创建Bean的方法
        public Bean3 createBean(){
            return new Bean3();
        }
    }

    测试类

    public class test(){
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans3.xml);
            System.out.println(applicationContext.getBean("bean3"));
        }
    }

    Bean的作用域

     

    Spring容器在初始化一个Bean实例时,可以同时为其指定特定的作用域。作用域的种类一共分为5种:singleton、prototype、request、session、global Session。

    1. singleton(单例模式)

    单例模式,使用singleton定义的Bean在Spring容器中将只有一个实例,也就是说,无论有多少个Bean引用它,始终指向同一个对象。(Spring默认)

    2. prototype(原型模式)

    原型模式,每次通过Spring容器获取的prototype定义的Bean时,容器都将新建一个新的Bean实例。

    3. request

    在一次HTTP请求中,容器会返回该Bean的同一个实例。对于不同的HTTP请求,会产生一个新的Bean,该Bean仅在当前HTTP Request内有效。

    4. session

    在一次HTTP Session中,容器会返回该Bean的同一个实例。对于不同的HTTP请求,会产生一个新的Bean,该Bean仅在当前HTTP Session内有效。

    5. global Session

    在一个全局的HTTP Session中,容器会返回该Bean的同一个实例。仅在使用portlet context时有效。

    上面这5种,singleton和prototype是最常用的。

    Singleton作用域

    单例模式对于无会话状态的Bean来说,是最理想的选择。(比如:Dao组件、Service组件)具体配置如下:

    <bean id="bean5" class="com.tm.bean.bean5" scope="singleton" />

    测试类

    public class test(){
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans5.xml);
            //两次输出是一样的
            System.out.println(applicationContext.getBean("bean5"));
            System.out.println(applicationContext.getBean("bean5"));
        }
    }

    Prototype作用域

    代码同Singleton一样,只需要将scope对应的属性值改成prototype即可。

    Bean的生命周期

    参考:https://www.cnblogs.com/javazhiyin/p/10905294.html 

    Bean的装配方式

    Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式,Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于Annotation的装配和自动装配等。

    基于XML的装配

    Spring依赖注入有两种方式:设值注入(Setter Injection)和构造注入(Constructor Injection)。

    在Spring实例化Bean的过程中,Spring首先调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:

    1. Bean类必须提供一个默认的构造方法。

    2. Bean类必须为需要注入的属性提供对应的setter方法。

    使用设值注入时,在Spring配置文件中,需要使用<bean>元素的子元素<property>元素来为每个属性注入值。

    使用构造注入时,在配置文件里,主要是使用<constructor-arg>标签来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

    User.java

    package cn.tm.bean;
    
    public class User{
        private String username;
        private Integer password;
        
        //默认构造
        public User(){
            super();
        }
        //构造方法注入
        public User(String username,Integer password){
            super();
            this.username = username;
            this.password = password;
        }
        //省略username和password的get、set方法,省略toString方法
    }

    Beans6.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--使用构造方式装配user实例-->
        <bean>
            <!-- 构造方式装配User类的实例。constructor-arg元素用来定义构造方法的参数,其属性值表示其索引,从0开始。value属性用于设置注入的值 -->
            <constructor-arg index="0" value="zhangsan"/>
            <constructor-arg index="1" value="1234"/>
        </bean>
        <!--使用Set方式装配user实例-->
        <bean>
            <!--设值注入方式装配User类的实例。使用其property元素用于调用Bean实例中的Setter方法完成属性赋值,从而完成依赖注入 -->
            <property name="username" value="lisi"></property>
            <property name="password" value="4321"></property>
        </bean>
    </beans>

    测试类

    public class test(){
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans6.xml);
            System.out.println(applicationContext.getBean("user1"));//输出zhangsan 1234
            System.out.println(applicationContext.getBean("user2"));//输出lisi 4321
        }
    }

    基于Annotation的装配

    XML配置文件的方式有时候过于臃肿,jdk1.5之后提供了Annotation(注解)功能,Spring也提供了对Annotation技术的全面支持。常用注解如下:

    (1)@Component:(把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>)

    可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。

    (2)@Repository:(实现dao访问)

    作用同@Component,用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件。用于将数据访问层(dao层)的类标识为Spring中的Bean。

    (3)@Service:(注入dao)

    作用同@Component,用于标注服务层,主要用来进行业务的逻辑处理。用于将业务层的类标识为Spring中的Bean。

    (4)@Controller:(注入服务)

    作用同@Component,通常作用在控制层(如Struts2的Action)。用于将控制层的类标识为Spring中的Bean。

    (5)@Autowired:

     用于对Bean的属性变量、属性的Set方法及构造函数进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。

    (6)@Resource:

    其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。

    (7)@Qualifier:

    与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

    在上面的注解中,虽然@Repository、@Service、@Controller功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议单独使用。

    下面演示如何通过这些注解来装配Bean:

    Beans7.xml

    这里要注意:相比上面的xml配置文件,这里头部分,新添加了两个context代码。http://www.springframework.org/schema/context和http://www.springframework.org/schema/context/spring-context.xsd

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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.xsd">
           
           <!-- 使用context命名空间,通知spring扫描指定目录,进行注解的解析 -->
           <context:component-scan base-package="cn.tm.bean"/>
    
    </beans>

    UserDao.java

    package cn.tm.bean;
    public interface UserDao{
        public void save();
    }

    UserDaoImpl.java

    package cn.tm.bean;
    //这里使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中<bean id="userDao" class="cn.tm.bean.userDaoImpl"/>的书写。
    @Repository("userDao")
    public class UserDaoImpl implements UserDao{
        public void save(){
            System.out.println("userdao...save...");
        }
    }

    UserService.java

    package cn.tm.bean;
    public interface UserService{
        public void save();
    }

    UserServiceImpl.java

    package cn.tm.bean;
    //@Service注解将UserServiceImpl类标识为Spring中的Bean,写法相当于配置文件中<bean id="userService" class="cn.tm.bean.UserServiceImpl" />的书写。
    @Service("userService")
    public class UserServiceImpl implements UserService{
        //使用@Resource注解标注在属性userDao上,也可以标注在userDao的set方法上,相当于配置文件中的<property name="userDao" ref="userDao"/>的写法。
        @Resource(name="userDao")
        private UserDao userDao;
        //userDao的set方法
        public void setUserDao(UserDao userDao){
            this.userDao = userDao;
        }
        public void save(){
            //调用userDao中的save方法
            this.userDao.save();
            System。out.println("userservice...save...");
        }
    }

    UserAction.java

    package cn.tm.bean;
    //使用@Controller注解标注UserAction类,写法相当于配置文件中的<bean id="userAction" class="cn.tm.bean.UserAction" />
    @Controller("userAction")
    public class UserAction{
        //相当于配置文件中的<property name="userService" ref="userService" />
        @Resource(name="userService")
        private UserService userService;
        //userService的set方法
        public void setUserService(UserService userService){
            this.userService = userService;
        }
        public void save(){
            //调用userService中的save方法
            this.userService.save();
            System.out.println("userAction...save...");
        }
    }

    测试类

    public class test(){
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(...beans7.xml);
            UserAction userAction = (UserAction)applicationContext.getBean("userAction");
            //输出实例
            System.out.println(userAction);
            //调用userAction中的save()方法
            userAction.save();
            //最后结果从上到下分别为
            //cn.tm.bean.UserAction@bffa22
            //userdao...save...
            //userservice...save...
            //userAction...save...
        }
    }

    自动装配

    所谓自动装配就是将一个Bean注入到其他Bean的Property中。

    要使用自动装配,就需要配置<bean>元素的autowire属性。autowire属性有5个值,说明如下:

    (1)byName:根据Property的Name自动装配,如果一个Bean的name,和另一个Bean中的Property的name相同,则自动装配这个Bean到Property中。

    (2)byType:根据Property的数据类型(Type)自动装配,如果一个Bean的数据类型,兼容另一个Bean中Property的数据类型,则自动装配。

    (3)constructor:根据构造函数参数的数据类型,进行byType模式的自动装配。

    (4)autodetect:如果发现默认的构造函数,用constructor模式,否则用byType模式。

    (5)no:默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义。

    将上面的Beans7.xml改进一下。

    Beans8.xml

    注意:默认情况下,配置文件中需要通过ref来装配Bean,但设置了autowire="byName",Spring会自动寻找与属性名字userDao相同的<bean>,找到后,通过调用setUserDao(UserDao userDao)将其注入属性,这时就不需要通过ref来装配了。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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.xsd">
           
           <bean id="userDao" class="cn.tm.bean.UserDaoImpl" />
           <bean id="userService" class="cn.tm.bean.UserServiceImpl" autowire="byName" />
           <bean id="userAction" class="cn.tm.bean.UserAction" autowire="byName" />
    </beans>

    参考:

    1. 《SSH框架整合实战教程》

    持续更新!!!

  • 相关阅读:
    使用try-with-resources偷懒关闭资源
    最小公倍数 分类: python 小练习 2013-12-02 11:19 263人阅读 评论(0) 收藏
    最大公约数 分类: python 小练习 2013-12-02 11:00 222人阅读 评论(0) 收藏
    Vim的Python编辑器详细配置过程 (Based on Ubuntu 12.04 LTS) 分类: ubuntu software 2013-11-30 00:05 652人阅读 评论(1) 收藏
    #小练习 合并首字母相同的男孩、女孩姓名 (最终版) 分类: python 小练习 2013-11-25 16:52 283人阅读 评论(0) 收藏
    输出文件中不包含指定的多个排除词的行内容(双重遍历) 分类: python 小练习 2013-11-22 15:20 605人阅读 评论(0) 收藏
    linux中tomcat内存溢出解决办法 分类: 测试 2013-11-22 09:46 5053人阅读 评论(0) 收藏
    将两个列表元素组成字典 分类: python 小练习 2013-11-12 18:17 750人阅读 评论(0) 收藏
    python:解析html(HTMLParser、SGMLParser) 分类: HTMLParser 2013-11-12 18:11 2302人阅读 评论(0) 收藏
    #小练习 使用SGMLParser获取url链接 分类: HTMLParser 2013-11-12 16:52 471人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/flyinghome/p/12607854.html
Copyright © 2011-2022 走看看