java框架学习日志-6(bean作用域和自动装配)

原创
2018/12/14 23:02
阅读数 179

本章补充bean的作用域和自动装配

bean作用域

之前提到可以用scope来设置单例模式

<bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean>

除此之外还有几种用法
singleton:单例模式,Spring默认使用单例模式,也是开发中最常用的类型。即:加载bean配置文件只能生成类的一个实例,只会new一次。
prototype:多例模式,用到一次就会new一次。因为对象多,所以不会销毁。
request:应用在web项目中,Spring创建这个类之后,将这个类存到request范围内。
session:应用在web项目中,Spring创建这个类之后,将这个类存到session范围内。
globalsession:应用在web项目中,必须在portlet环境下才能使用。即在系统下存入数据后,在其子系统下就不需要重新登录。
注意默认情况下bean的作用域是单例。之前我有个疑问,既然是单列,为什么可以在java代码中创建两个实例对象?如下图

        ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
        Student student=(Student)ac.getBean("student");
        Student student1=(Student)ac.getBean("student");

其实这里的getBean获取的bean都是一个bean。我们改student的名字,student1的名字也会改变。因为student在容器里只有一个。

        ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
        Student student=(Student)ac.getBean("student");
        Student student1=(Student)ac.getBean("student");
        student.show();
        student.setName("王五");
        student1.show();


改成prototype

<bean id="student" class="cn.dota2.hero.Student" scope="prototype">
        <property name="name" value="张三"/>
    </bean
        ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
        Student student=(Student)ac.getBean("student");
        Student student1=(Student)ac.getBean("student");
        student.show();
        student.setName("王五");
        student.show();
        student1.show();

bean自动装配

一个bean文件可能需要引用其他很多bean,这样配置文件可能会很复杂,所有有了自动装配来简化spring。
常规引用

package cq.school.student;

import cq.school.School;

public class Student {
    School school=null;

    public School getSchool() {
        return school;
    }

    public void setSchool(School school) {
        this.school = school;
    }
    public void show(){
        school.getSchool();
    }
}

bean配置

    <bean id="frist" class="cq.school.FristSchool"/>
    <bean id="second" class="cq.school.SecondSchool"/>
    <bean id="student" class="cq.school.student.Student">
        <property name="school" ref="frist"/>

自动装配有几种种

通过byname自动装配。

<bean id="student" class="cq.school.student.Student" autowire="byName">

这里的name是Student中的setSchoole中的school。它会在bean容器中寻找name相符合的自动装配。所以需要更改frist或者second的id或者name。代码如下

    <bean id="school" class="cq.school.SecondSchool"/>
    <bean id="student" class="cq.school.student.Student" autowire="byName">


java代码中给school赋值的方法时setSchool,所以会把id为school传给student。

通过byType装配。

    <bean  class="cq.school.FristSchool"/>
    <bean  class="cq.school.SecondSchool"/>
    <bean id="student" class="cq.school.student.Student" autowire="byType"/>

和byname相似,会自动寻找类型相符合的装配,测试一下
报错原因是因为一中和二中都是符合类型的,要删除一个才行,用bytpye装配需要整个容器只有一个相符合的类型。删除一个后

    <bean  class="cq.school.SecondSchool"/>
    <bean id="student" class="cq.school.student.Student" autowire="byType"/>


如果所有配置都需要用到一种配置方式,可以在头文件中加入default-autowire="byName"。或者换成其他配置方法

<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-2.5.xsd" default-autowire="byName">

consrtuctor注入。

通过构造器注入。适用于bytype得而方式装配构造器,修改一下student的代码,去掉set方法,让它在构造方法里面设置school。

package cq.school.student;

import cq.school.School;

public class Student {
    School school=null;
    public Student(School school){//修改处
        this.school=school;
    }

    public School getSchool() {
        return school;
    }

    public void show(){
        school.getSchool();
    }
}

自动装配改成改成constructor注入

<?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-2.5.xsd" default-autowire="byName">
    <bean  class="cq.school.SecondSchool"/>
    <bean id="student" class="cq.school.student.Student" autowire="constructor"/>
</beans>

结果一样。

总结

在配置bean时,有 scope属性,可以配置bean作用域,在整合struts2和spring时,需要将action设为scope=“prototype”;(目前不知道为啥,反正记住),关于自动装配,用于减少配置文件。我自己感觉自动装配虽然简洁了代码,但是太过简洁反而不利于阅读,特别是bytype装配,bean一旦太多,就容易出bug,而且不好排查。建议少用。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
4 收藏
0
分享
返回顶部
顶部