继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Spring IOC/DI学习小结Ⅰ

亚努人
关注TA
已关注
手记 20
粉丝 36
获赞 349

在Spring IOC/DI的学习中,核心的内容就是Bean装配及相关内容了。其中Bean配置有两种方式,分别是基于XML文件配置Bean和基于注解配置Bean,本篇总结这两种方式的基本使用。

一、基于XML文件配置Bean
1.1 全类名(反射)方式

通过全类名的方式在IOC中创建Bean,先决条件是Bean中必须有无参构造方法。在XML文件中使用bean标签和id、class属性实例化Bean。

<bean id="bean标识" class="全类名">
    ...... //属性注入或构造器注入
</bean>

其中属性注入是通过<property>标签,使用name指定属性名,value指定属性值,对Bean中的属性进行赋值。构造器注入是通过<constructor-arg>标签,使用value为参数传值,为了区分重载的构造器,通常会配合使用type属性,指定参数的类型。如下案例,有Student和Course两个Bean,通过全类名方式对他们进行装配。

public class Student {
    private String sname;
    private int sno;
    private Course course;

    public Student() {
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "Student [sname=" + sname + ", sno=" + sno + ", course=" + course + "]";
    }

}
public class Course {
    private String cname;
    private String tname;

    public Course() {
    }

    public Course(String cname, String tname) {
        super();
        this.cname = cname;
        this.tname = tname;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    @Override
    public String toString() {
        return "Course [cname=" + cname + ", tname=" + tname + "]";
    }

}
<?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="student" class="com.spring.beans.test.Student">
        <property name="sno" value="101"></property>
        <property name="sname" value="张三"></property>
        <property name="course" ref="course1"></property>
        <!--由于course属性是关联到Course类的,所以使用ref属性引用bean-->
    </bean>

    <bean id="course1" class="com.spring.beans.test.Course">
        <constructor-arg type="java.lang.String">
            <value><![CDATA[<c#程序设计>]]></value>
            <!--假定字符串中包含与XML冲突的特殊字符,用CDATA进行处理-->
        </constructor-arg>
        <constructor-arg value="Mr.C" type="java.lang.String"></constructor-arg>
    </bean>

</beans>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        //1、创建spring的IOC容器对象,从类路径下加载文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-test.xml");
        //2、从IOC容器对象中获取bean实例
        Student student = (Student) ctx.getBean("student");
        Course course = (Course) ctx.getBean("course1");
        System.out.println(student);
        System.out.println(course);
    }
}

运行结果如下图所示:
图片描述

也可以在student的bean中,通过级联的方式为course赋值,但首先还是要引用course的bean。如下代码所示:

<bean id="student" class="com.spring.beans.test.Student">
        <property name="sno" value="101"></property>
        <property name="sname" value="张三"></property>

        <property name="course" ref="course1"></property>
        <property name="course.cname" value="Java程序设计"></property>
        <property name="course.tname" value="Mr.J"></property> 
    </bean>

一个学生可以参加多门课程,当学生的课程属性是List集合类型或者Map类型时,相关的配置如下代码所示:

    <bean id="student" class="com.spring.beans.test.Student">
        <property name="sno" value="101"></property>
        <property name="sname" value="张三"></property>
        <property name="course" >
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property> 
    </bean>
    <bean id="student" class="com.spring.beans.test.Student">
        <property name="sno" value="101"></property>
        <property name="sname" value="张三"></property>
        <property name="course" >
            <map>
                <entry key="C#" value-ref="course1" />
                <entry key="Java" value-ref="course2" />
            </map>
        </property> 
    </bean>
1.2 通过工厂方法配置

静态工厂方法:直接调用某一个类的静态方法,就可以返回bean的实例

public class StaticCourseFactory {
    private static Map<String,Course> courses = new HashMap<String,Course>();
    static{
        courses.put("基础课", new Course("大学英语","Mr.E"));
        courses.put("专业课", new Course("操作系统","Mr.C"));
    }

    //静态工厂方法
    public static Course getCourse(String name){
        return courses.get(name);
    }
}
    <!-- 通过静态工厂方法配置bean实例,class属性指向静态方法的全类名
        factory-method:指向静态工厂方法的方法名,通过constructor-arg子标签传递参数值
     -->
    <bean id="course3" class="com.spring.beans.test.StaticCourseFactory" factory-method="getCourse">
        <constructor-arg value="基础课"></constructor-arg> <!-- 传参数 -->
    </bean>

实例工厂方法:首先配置工厂的实例,然后通过实例工厂方法来配置bean,factory-bean属性指向实例方法的bean,factory-method指向实例工厂方法的方法名,通过constructor-arg子标签传递参数值

    <bean id="InstanceFactory" class="com.spring.beans.test.InstanceCourseFactory"></bean>
    <bean id="course4" factory-bean="InstanceFactory" factory-method="getCourse">
        <constructor-arg value="专业课"></constructor-arg>
    </bean>
1.3 通过FactoryBean配置

定义一个类实现FactoryBean接口,重写相关的方法。在XML中进行bean配置(与全类名配置相似),返回的是FactoryBean中的getObject()方法。

二、基于注解配置Bean
@Component:基本注解,标识一个受Spring管理的基本组件
@Controller:标识表现层的组件
@Service:标识业务层的组件
@Respository:标识持久层组件

以上注解有一个默认的属性value,可以用来标识IOC中的id。在组件类上使用特定的注解后,还需要在Spring的配置文件中声明<context:component-scan>,其中base-package属性指定要扫描的包及其子包,resource-pattern属性是只扫描指定包的类。

@Component("course5")
public class Course {
    private String cname;
    private String tname;

    public Course() {
    }
    ...... //其他get、set部分代码省略
}
<?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.0.xsd">

     <context:component-scan base-package="com.spring.beans.test"></context:component-scan>

</beans>
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-test.xml");
        Course course = (Course) ctx.getBean("course5");
        System.out.println(course);
    }
}

其他几个注解的使用方法也是一样,只是在使用的地方(各个层)有区别。在使用<context:component-scan>时,还有<context:exclude-filter><context:include-filter>等子标签,他们的作用分别是不包含指定组件和只包含指定组件,使用后者的时候要将父标签的use-default-filter的值设为false。

打开App,阅读手记
2人推荐
发表评论
随时随地看视频慕课网APP