spring-01


spring学习-day01

一、IOC和DI

IOC:控制反转,把创建对象和对象之间的调用过程交给spring来管理,就是将设计好的对象交给容器来管理

eg:我们在学习spring的时候在xml配置文件中就把bean对象写好了,然后想要获取对象只要调用getBean方法就可以获取对应的对象。因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单,可以使耦合度降低。

DI:依赖注入就是组件之间的依赖关系由容器在运行时决定,简单点说就是容器动态的将某个依赖关系注入到组件中。再通俗点就是注入属性

二、Spring 提供 IOC 容器实现两种方式

 1. BeanFactory:是spring内部的使用接口。
 2. ApplicationContext:BeanFactory的一个子接口,在原来的基础上提供了更强大的功能。

BeanFactory和ApplicationContext的区别主要是:

BeanFactory在加载配置文件时不会创建对象,只有在使用的时候(即获取对象的时候)创建
对象,而ApplicationContext在加载配置文件的时候就会把配置文件中的对象给创建。

三、两种实现方式

1. 基于xml方式实现
2. 基于注解方式实现

1、基于xml方式注入属性

1) 通过set方式注入

实体类:

public class User {
    /**
     * 用户名
     */
    private String userName;
    /**
     * 用户编号
     */
    private String userId;
    /**
     * 用户邮编地址
     */
    private String address;
    /**
     * 用户邮箱
     */
    private String email;
    /**
     * 家乡
     */
    private String countrySide;

    public void setCountrySide(String countrySide) {
        this.countrySide = countrySide;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", userId='" + userId + '\'' +
                ", address='" + address + '\'' +
                ", email='" + email + '\'' +
                ", countrySide='" + countrySide + '\'' +
                '}';
    }
}

xml配置文件:
注意:这里添加了注入空值null和特殊字符的情况

<?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 ">

    <!--
        1、通过set方式注入
    -->
    <bean id="user" class="com.spring.entity.User">
        <property name="userName" value="Tom"></property>
        <property name="userId" value="26181"></property>
        <!--
            注入相关的null(空值)
        -->
        <property name="address">
            <null></null>
            <!--
                <null/>
            -->
        </property>
        <property name="email" value="2420136827@qq.com"></property>
        <!--
            属性值包含特殊符号,例如<>
                反例:<property name="email" value="<南京>"></property>
            把带特殊字符内容写到CDATA
        -->
        <property name="countrySide">
            <value><![CDATA[<<江苏南京>>>]]]></value>
        </property>
    </bean>

</beans>

测试类:

@Test
    public void userTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user.toString());
    }

对于初学者,需要提一下的是测试方法中的context.getBean(“user”, User.class)的"user"指的是配置文件中对应的id值。

测试结果:

User{userName='Tom', userId='26181', address='null', email='2420136827@qq.com', countrySide='<<江苏南京>>>]'}
2) 通过有参构造方式注入

实体类:

public class Book {
    private String bookName;
    private String bookPrices;

    public Book(String bookName, String bookPrices) {
        this.bookName = bookName;
        this.bookPrices = bookPrices;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookName='" + bookName + '\'' +
                ", bookPrices='" + bookPrices + '\'' +
                '}';
    }
}

xml配置文件中对应的bean实例

	<!--
        2、通过有参数构造方式注入
    -->
    <bean class="com.spring.entity.Book" id="book">
        <constructor-arg name="bookName" value="假如给我三天光明"></constructor-arg>
        <constructor-arg name="bookPrices" value="32.4"></constructor-arg>
    </bean>

测试方法

@Test
    public void bookTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Book book = context.getBean("book", Book.class);

        System.out.println(book.toString());
    }

测试结果:

Book{bookName='假如给我三天光明', bookPrices='32.4'}
3) 通过p名称空间注入

注意:p名称空间注入主要是对于set方式注入的一种简化,并且观察下面的配置文件的相应变化(xmlns:p=“http://www.springframework.org/schema/p”)

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
        3、通过名称空间注入
    -->
    <bean class="com.spring.entity.User" id="user2" p:userId="26191" p:userName="Jack"></bean>
</beans>

测试类和测试方法和上面通过set方法注入雷同。
测试结果:

User{userName='Jack', userId='26191', address='null', email='null', countrySide='null'}
4) 注入外部bean

这里使用Dao和Service来举例:
Dao层:

public interface UserDao {
    void update();
}

public class UserDaoImpl implements UserDao{

    @Override
    public void update() {
        System.out.println("update ......");
    }
}

Service层:

public class UserService {
    // 创建UserDao类型属性,生成set方法
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void add(){
        System.out.println("service add ......");
        userDao.update();
    }
}

配置文件:

<?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 -->

    <!-- 1、service和dao对象的创建 -->
        <bean class="com.spring.service.UserService" id="userService">
            <!-- 注入userDao对象
                name为属性只,类里面的属性名称
                ref属性:注入外部bean的id值(这里是userDao)
            -->
            <property name="userDao" ref="userDao"></property>
        </bean>

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

测试类:

@Test
    public void test(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean.xml");

        UserService userService = context.getBean("userService", UserService.class);

        userService.add();

    }

测试结果:

service add ......
update ......
5) 注入内部bean

这里用员工和部门来举例子,一个部门有多个员工,一个员工只有一个所在部门,属于一对多的关系,我们只需要再员工类里面添加一个部门属性就可以实现。
部门类:

public class Dept {
    private String deptName;

    private String deptNo;

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public void setDeptNo(String deptNo) {
        this.deptNo = deptNo;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptName='" + deptName + '\'' +
                ", deptNo='" + deptNo + '\'' +
                '}';
    }
}

员工类:

public class Emp {
    /**
     * 员工姓名
     */
    private String empName;
    /**
     * 员工编号
     */
    private String empNo;
    /**
     * 所在部门
     */
    private Dept dept;

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    /**
     * 下面的getDept用于级联复制(第三种方式)
     * @return
     */
    public Dept getDept() {
        return dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empName='" + empName + '\'' +
                ", empNo='" + empNo + '\'' +
                ", dept=" + dept +
                '}';
    }
}

xml配置文件:

<!-- 注入内部bean,比如对于一对多的关系:员工Emp和部门Dept -->
    <bean class="com.spring.entity.Emp" id="emp">
        <property name="empName" value="小芳"></property>
        <property name="empNo" value="26181"></property>
        <!-- 注入内部bean -->
        <property name="dept">
            <bean class="com.spring.entity.Dept" id="dept">
                <property name="deptName" value="公共研发部(注入内部bean)"></property>
                <property name="deptNo" value="26100"></property>
            </bean>
        </property>
    </bean>

测试:

/**
     * 下面的测试是对于注入内部bean的测试
     */
    @Test
    public void test(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");

        Emp emp = context.getBean("emp", Emp.class);
        System.out.println(emp);

    }

结果:

Emp{empName='小芳', empNo='26181', dept=Dept{deptName='公共研发部(注入内部bean)', deptNo='26100'}}

另一种注入属性的写法:
注意:这种写法要在员工类中添加部门的getter方法,以获取对象

<!-- 级联赋值 -->

    <bean class="com.spring.entity.Emp" id="emp3">
        <property name="empName" value="小芳"></property>
        <property name="empNo" value="26181"></property>
        <!-- 1、级联赋值 -->
        <property name="dept" ref="dept3"></property>
        <!--
            注意:这种方式要在Emp中添加Dept的getter方法来获取外部对象(dept3)
        -->
        <property name="Dept.deptName" value="公共研发部(级联赋值)"></property>
        <property name="Dept.deptNo" value="26100"></property>
    </bean>
    <bean class="com.spring.entity.Dept" id="dept3"></bean>

测试:

/**
     * 下面的测试是对于级联赋值的第二种写法
     */
    @Test
    public void test3(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");

        Emp emp = context.getBean("emp3", Emp.class);
        System.out.println(emp);

    }

结果:

Emp{empName='小芳', empNo='26181', dept=Dept{deptName='公共研发部(级联赋值)', deptNo='26100'}}
6) 集合属性的注入
1-普通集合注入

类:

public class Library {
    /**
     * 数组属性
     */
    private String[] arrays;

    /**
     * List集合属性
     */
    private List<String> list;

    /**
     * Map集合属性
     */
    private Map<String,String> map;

    /**
     * set结合属性
     */
    private Set<String> sets;

    public void setArrays(String[] arrays) {
        this.arrays = arrays;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }

    @Override
    public String toString() {
        return "Library{" +
                "arrays=" + Arrays.toString(arrays) +
                ", list=" + list +
                ", map=" + map +
                ", sets=" + sets +
                '}';
    }
}

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 class="com.spring.entity.Library" id="library">
        <!-- 对于数组属性的注入 -->
        <property name="arrays">
            <array>
                <value>1</value>
                <value>2</value>
                <value>3</value>
                <value>4</value>
                <value>5</value>
                <value>5</value>
            </array>
        </property>

        <!-- 对于map属性的注入 -->
        <property name="map">
            <map>
                <entry key="1" value="张三"></entry>
                <entry key="2" value="李四"></entry>
                <entry key="3" value="王五"></entry>
            </map>
        </property>

        <!-- 对于List属性的注入 -->
        <property name="list">
            <list>
                <value>假如给我三天光明</value>
                <value>假易筋经</value>
                <value>钢铁是怎样炼成的</value>
                <value>三体</value>
            </list>
        </property>

        <!-- 对于Set属性的注入 -->
        <property name="sets">
            <set>
                <value>Mysql</value>
                <value>Redis</value>
                <value>Java</value>
                <value>Java</value>
            </set>
        </property>
    </bean>
</beans>

测试:

@Test
    public void test(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean2.xml");

        Library library = context.getBean("library", Library.class);

        System.out.println(library);

    }

结果:

Library{arrays=[1, 2, 3, 4, 5, 5], list=[假如给我三天光明, 假易筋经, 钢铁是怎样炼成的, 三体], map={1=张三, 2=李四, 3=王五}, sets=[Mysql, Redis, Java]}
2-集合对象注入

其实有点类似于普通的集合注入,区别主要是value和ref的更换,以及相关的bean的创建,value主要是针对普通数据类型,ref主要是引用数据类型(对象)。
类:

public class Course {
    private String courseName;

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                '}';
    }
}
public class CourseConnection {
    private List<Course> courseList;

    private Course[] courseArrays;

    private Map<String,Course> map;

    private Set<Course> sets;

    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }

    public void setCourseArrays(Course[] courseArrays) {
        this.courseArrays = courseArrays;
    }

    public void setMap(Map<String, Course> map) {
        this.map = map;
    }

    public void setSets(Set<Course> sets) {
        this.sets = sets;
    }

    @Override
    public String toString() {
        return "CourseList{" +
                "courseList=" + courseList +
                ", \ncourseArrays=" + Arrays.toString(courseArrays) +
                ", \n map=" + map +
                ", \n sets=" + sets +
                '}';
    }
}

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 class="com.spring.entity.Course" id="course">
        <property name="courseName" value="Spring5"></property>
    </bean>
    <bean class="com.spring.entity.Course" id="course2">
        <property name="courseName" value="Mybatis"></property>
    </bean>
    <bean class="com.spring.entity.Course" id="course3">
        <property name="courseName" value="SpringMVC"></property>
    </bean>

    <bean class="com.spring.entity.CourseConnection" id="courses">
        <!-- List对象集合 -->
        <property name="courseList">
            <list>
                <ref bean="course"></ref>
                <ref bean="course2"></ref>
                <ref bean="course3"></ref>
            </list>
        </property>

        <!-- Array对象集合 -->
        <property name="courseArrays">
            <array>
                <ref bean="course"></ref>
                <ref bean="course2"></ref>
                <ref bean="course3"></ref>
            </array>
        </property>

        <!-- map对象集合 -->
        <property name="map">
            <map>
                <entry key="1" value-ref="course"></entry>
                <entry key="2" value-ref="course2"></entry>
                <entry key="3" value-ref="course3"></entry>
            </map>
        </property>
        <!-- set对象集合 -->
        <property name="sets">
            <set>
                <ref bean="course"></ref>
                <ref bean="course2"></ref>
                <ref bean="course3"></ref>
                <ref bean="course"></ref>
            </set>
        </property>
    </bean>

</beans>
3-提取公共部分

提取公共部分,可以实现资源的共享,这里使用到了util标签。
实体类还是Librery类
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"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!--
        把集合注入部分提取出来(即共享集合,脱离特有的对象)
    -->
    <util:list id="list">
        <value>假如给我三天光明</value>
        <value>假易筋经</value>
        <value>钢铁是怎样炼成的</value>
        <value>三体</value>
    </util:list>

    <util:map id="map">
        <entry key="1" value="张三"></entry>
        <entry key="2" value="李四"></entry>
        <entry key="3" value="王五"></entry>
    </util:map>

    <util:set id="set">
        <value>Mysql</value>
        <value>Redis</value>
        <value>Java</value>
        <value>Java</value>
    </util:set>

    <!-- 对于注入集合属性的使用 -->
    <bean class="com.spring.entity.Library" id="library">
        <!-- 对于数组属性的注入 -->
        <property name="arrays">
            <array>
                <value>1</value>
                <value>2</value>
                <value>3</value>
                <value>4</value>
                <value>5</value>
                <value>5</value>
            </array>
        </property>
        <!-- 对于map属性的注入 -->
        <property name="map" ref="map"></property>
        <!-- 对于List属性的注入 -->
        <property name="list" ref="list"></property>
        <!-- 对于Set属性的注入 -->
        <property name="sets" ref="set"></property>
    </bean>
    
</beans>

测试:

@Test
    public void test(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean3.xml");

        Library library = context.getBean("library", Library.class);

        System.out.println(library);

    }

结果:

Library{arrays=[1, 2, 3, 4, 5, 5], list=[假如给我三天光明, 假易筋经, 钢铁是怎样炼成的, 三体], map={1=张三, 2=李四, 3=王五}, sets=[Mysql, Redis, Java]}

四、bean的作用域

实体类使用前面的Course类
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">

    <!--
        scope:
            singleton:创建单实例
            prototype:创建多实例(类似于克隆)

    -->
    <bean class="com.spring.entity.Course" id="course" scope="prototype"></bean>
</beans>

测试:

 @Test
    public void scopeTest(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean4.xml");

        Course course = context.getBean("course", Course.class);
        Course course1 = context.getBean("course", Course.class);
        if(course==course1){  // hashCode
            System.out.println("单实例");
        }
        else{
            System.out.println("多实例");
        }

    }

结果:

多实例

写这个文章主要是用于自己对知识点的梳理,当然也有想让各位跟我一样的小白参考,作者学识浅薄,有可能有错误,所以欢迎纠错,一起学习讨论,一起进步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值