Spring框架-IOC容器的Bean管理(基于xml配置方式)

 

1.Spring框架的简介。

什么是Spring框架:

 Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。

  简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

Spring框架模型:

 

Spring5的下载地址:

https://repo.spring.io/release/org/springframework/spring/

可以选择已经发行的版本进行下载:

选择下载即可:

下载之后,就可以在idea中创建一个普通的Java工程,然后再导入相应的jar包就行。

Ioc基础jar包:core containers

2.Spring核心之一:IOC(Inversion of Control,即控制反转。它不是什么技术,而是一种设计思想。)

传统的创建对象的方法是直接通过 new 关键字,而 spring 则是通过 IOC 容器来创建对象,也就是说我们将创建对象的控制权交给了 IOC 容器。我们可以用一句话来概括 IOC:

  IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建、初始化、销毁等工作交给spring容器来做。

IOC的通俗理解:

 IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。

  那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

在不用Spring之前:

使用IOC:

3.利用Spring来创建对象:

1.IOC的思想基于IOC容器完成,IOC容器底层就是对象工厂

2.Spring提供IOC容器实现的两种方式:(也就是两个接口)

  • BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用

加载配置文件的时候不会创建对象,在获取对象(使用)的时候才去创建对象

  • ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用。

加载配置文件时候就会把在配置文件中的对象进行创建。

3.ApplicationContext接口的实现类

FileSystemXmlApplicationContext:是系统路径的配置文件,也就是包含盘符的配置文件的路径

ClassPathXmlApplicationContext:是在当前src目录下的配置文件。

IOC操作bean管理

1.什么是bean管理:bean管理指的是两个操作

  • Spring创建对象:
  • Spring注入属性:

2.bean管理操作有两种方式:

  • 基于xml配置文件方式实现
  • 基于注解方式实现

4.方式一:基于xml方式进行bean管理(普通的bean)

1.基于xml方式创建对象:

在src在创建xml文件:

在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建

在bean标签中有很多属性,介绍常用的属性

  • id属性:唯一标识
  • class属性:类全路径(包和类路径)

创建对象时候,默认也是执行无参数构造方法完成对象的创建。

 

  <!--配置User对象-->
    <bean id="user" class="com.lsy.bean.User">

    </bean>
package com.lsy.bean;

/**
 * @Description:  User的bean对象
 * @Author:lsy
 * @Date:
 */
public class User {
    public void add(){
        System.out.println("Add---");
    }
}





//测试类
 /**
     * UserTest
     */
    @Test
    public void test1(){
        //1.加载Spring的配置文件
        //文件路径默认在src下。
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        User user = context.getBean("user", User.class);
        System.out.println(user);
        user.add();
    }

2.基于xml方式注入属性(DI:依赖注入,就是注入属性)

两种方式:

  • 方式一:使用set方法进行注入
package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Book {
    private String bname;
    private String bauthor;
  
    

    public void setBname(String bname) {
        this.bname = bname;
    }
    
    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
    public void testBook(){
        System.out.println(bname+":"+bauthor);
    }
}
 <bean id="book" class="com.lsy.bean.Book">
        <property name="bname" value="时间简史"></property>
        <property name="bauthor" value="霍金"></property>


    </bean>

 

    @Test
    public void test2(){
        //1.加载Spring的配置文件
        //文件路径默认在src下。
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        Book book = context.getBean("book", Book.class);
        System.out.println(book);
        book.testBook();
    }

 

  • 方式二:使用有参数构造方法进行注入
package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Orders {
    private String oname;
    private String address;


    //有参构造

    public Orders(String oname, String address) {
        this.oname = oname;
        this.address = address;
    }
    public void ordertest(){
        System.out.println("ordertest");
    }
}

bean1.xml文件中

    <bean id="orders" class="com.lsy.bean.Orders">
        <constructor-arg name="oname" value="computer"></constructor-arg>
        <constructor-arg name="address" value="china"></constructor-arg>
    </bean>

方式三:P名称空间注入

第一步:添加p名称空间在配置文件中。

第二步:进行属性注入,在bean标签里面进行操作

  <bean id="book" class="com.lsy.bean.Book" p:bname="tomcat" p:bauthor="lsy">

    </bean>

xml注入其他类型的属性:空值和含有特殊符号的属性值。


<!--        可以设置null值-->
<!--        <property name="address" >-->
<!--            <null/>-->
<!--        </property>-->
<!--        含有特殊的字符,报错-->
<!--        <property name="address" value="<<南京>>">-->
<!--            -->
<!--        </property>-->

<!--        可以用转移字符 &lt,&gt或者是CDATA-->
        <property name="address">
            <value>
                <![CDATA[<<南京>>]]>
            </value>
        </property>

    </bean>

    <bean id="orders" class="com.lsy.bean.Orders">
        <constructor-arg name="oname" value="computer"></constructor-arg>
        <constructor-arg name="address" value="china"></constructor-arg>
    </bean>



</beans>

3.注入属性:外部bean

  • 创建两个service类和dao类。
  • 在service调用dao里面的方法。
  • 在Spring配置文件中进行配置。
package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class UserService {
   private UserDao userDao;

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

    }

    @Override
    public String toString() {
        return "UserService{" +
                "userDao=" + userDao +
                '}';
    }
}



package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class UserDaoImpl implements UserDao{

    @Override
    public void update() {
        System.out.println("UserDaoImpl 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" 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">

    <bean id="userDaoImpl" class="com.lsy.bean.UserDaoImpl">

    </bean>
    <bean id="userService" class="com.lsy.bean.UserService">
        <!--注入userDao对象
             name属性:类里面属性名称
             ref属性:创建userDao对象bean标签id值,也就是外部bean标签
         -->
        <property name="userDao" ref="userDaoImpl"></property>

    </bean>
</beans>

Test类:

    /**
     * 外部bean的使用
     */
    @Test
    public void test4(){
        //1.加载Spring的配置文件
        //文件路径默认在src下。
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }

 

4.注入属性:内部bean

  • 当类与类之间存在一对多的关系时,可以使用内部bean来进行实现注入属性
  • 一对多的关系:部门和员工,一个部门中有多个员工,一个员工属于一个部门
  • 在员工类中设置相应部门的属性,表示所属的部门。
package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Emp {
    private String name;
    private String gender;
    //员工所属的部门,使用对象的形式进行表示
    private Dept dept;


    public void setName(String name) {
        this.name = name;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

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







package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Dept {
    private String Deptname;

    public void setDeptname(String deptname) {
        Deptname = deptname;
    }

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

 

<!--    内部bean-->
    <bean id="emp" class="com.lsy.bean.Emp">

        <property name="name" value="lisa"></property>
        <property name="gender" value="女"></property>

<!--        设置对象类型属性-->
        <property name="dept">
            <bean id="dept" class="com.lsy.bean.Dept">
                <property name="deptname" value="财务部"></property>
            </bean>
        </property>
    </bean>

Test测试类:

    /**
     * 内部类的使用
     */
    @Test
    public void test5(){
        //1.加载Spring的配置文件
        //文件路径默认在src下。
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        Emp emp = context.getBean("emp", Emp.class);
        System.out.println(emp);
    }

5.注入属性:级联赋值

    <!--级联赋值-->
    <bean id="emp" class="com.atguigu.spring5.bean.Emp">
        <!--设置两个普通属性-->
        <property name="ename" value="lucy"></property>
        <property name="gender" value="女"></property>
        <!--级联赋值-->
        <property name="dept" ref="dept"></property>
<!--要在Emp类中设置相应的get方法-->
        <property name="dept.dname" value="技术部"></property>
    </bean>
    <bean id="dept" class="com.atguigu.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

6.IOC操作Bean管理(xml注入集合属性)

  • 注入数组类型属性
  • 注入List集合属性
  • 注入Map集合类型属性
package com.lsy.bean;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Stu {
    //1 数组类型属性
    private String[] courses;
    //2 list集合类型属性
    private List<String> list;
    //3 map集合类型属性
    private Map<String,String> maps;
    //4 set集合类型属性
    private Set<String> sets;

    //学生所学多门课程
    private List<Course> courseList;


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

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
    public void setCourses(String[] courses) {
        this.courses = courses;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

    public void test() {
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courseList);
    }
}




package com.lsy.bean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Course {
    private String cname; //课程名称
    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

xml

<!--    集合属性的配置-->
    <bean id="stu" class="com.lsy.bean.Stu">
        <!--数组类型属性的注入-->
        <property name="courses">
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <!--list类型属性注入-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
            </list>
        </property>

        <!--map类型属性注入-->
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>

        <!--set类型属性注入-->
        <property name="sets">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>

        <!--注入list集合类型,值是对象-->
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>

    </bean>

<!--    创建多个course对象-->

    <bean id="course1" class="com.lsy.bean.Course">
        <property name="cname" value="Spring5"></property>

    </bean>
    <bean id="course2" class="com.lsy.bean.Course">
        <property name="cname" value="MyBatis"></property>

    </bean>

7.把节注入部分还可以提取出来

在Spring配置文件中引入名字空间util

配置bean标签

package com.lsy.bean;

import java.util.List;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Food {
    private List<String> list;

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

    public void test(){
        System.out.println(list);
    }
}
<?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"
       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="listfood">
        <value>apple</value>
        <value>rice</value>
        <value>番茄</value>
        <value>tofu</value>
    </util:list>
    <bean id="food" class="com.lsy.bean.Food">
        <property name="list" ref="listfood"></property>

    </bean>

5.基于xml方式进行bean管理(FactoryBean)

1.Spring有两种类型Bean,一种是普通的bean,另外一种是工厂bean(FactoryBean)

2.普通的bean:在配置文件中定义bean类型就是返回类型(也就是说在bean标签中配置的class是什么类型返回的就是该类型的实例对象)

3.工厂bean:在配置文件中定义的bean类型可以和返回类型不一样。

第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean

第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型。

package com.lsy.factorybean;

import com.lsy.bean.Course;
import org.springframework.beans.factory.FactoryBean;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class MyBean implements FactoryBean<Course> {


    /**
     *可以增加泛型,即使在Bean标签中配置的是MyBean但是返回类型是Course类型。
     * @return 返回Course
     * @throws Exception
     */
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("abc");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}



package com.lsy.factorybean;

import com.lsy.bean.Course;
import com.lsy.bean.Food;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class MyBeanTest {
    @Test
    public void test(){
        //1.加载Spring的配置文件
        //文件路径默认在src下。
        ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
        //2.获取配置创建的对象
        Course course = context.getBean("myBean", Course.class);
        System.out.println(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"
       xmlns:p="http://www.springframework.org/schema/p"
       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 ">

    <bean id="myBean" class="com.lsy.factorybean.MyBean">

    </bean>

</beans>

6.IOC 操作Bean管理(bean作用域)

在Spring里面,可以设置创建bean实例时是单实例还是多实例

在Spring里面,默认概况下是单实例对象

如何设置是单实例还是多实例

1.在Spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例

2.scope属性值

  • 第一个值:默认值,singleton,表示是单实例对象
  • 第二个值 prototype,表示是多实例对象

singleton和prototype区别

7.IOC操作bean管理(bean的声明周期)

生命周期:从对象创建到对象销毁的过程。

package com.lsy.timetest;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class Order {
    //无参数构造
    public Order() {
        System.out.println("第一步 执行无参数构造创建bean实例");
    }

    private String oname;
    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步 调用set方法设置属性值");
    }

    //创建执行的初始化的方法,在配置文件中进行配置
    public void initMethod() {
        System.out.println("第三步 执行初始化的方法");
    }

    //创建执行的销毁的方法,需要在配置文件中进行配置
    public void destroyMethod() {
        System.out.println("第五步 执行销毁的方法");
    }
}





package com.lsy.timetest;

import com.lsy.bean.Food;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description:
 * @Author:lsy
 * @Date:
 */
public class TimeTest {
    @Test
    public void test(){


        //1.加载Spring的配置文件
        //文件路径默认在src下。
//        ApplicationContext context=new ClassPathXmlApplicationContext("bean3.xml");
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean3.xml");

        //2.获取配置创建的对象
        Order order = context.getBean("order", Order.class);
        System.out.println("第四步 获取创建bean实例对象");
        System.out.println(order);
        //手动让bean实例销毁,调用bean中配置的销毁函数
        context.close();//第五步
    }
}

 

<?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="order" class="com.lsy.timetest.Order" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="phone"></property>
    </bean>

</beans>

如果在配置将bean添加后置处理器,那么bean的生命周期就会有七步,在初始化方法的前后,

在配置文件中配置了后置处理器之后,就会在配置文件加载的时候,为配置文件中的每一个bean都配置一个后置处理器。

public class MyBeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("在初始化之后执行的方法");
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }
}
 <bean id="myBeanPost" class="com.lsy.timetest.MyBeanPost"></bean>

8.IOC操作bean管理(xml的自动装配)

什么是自动装配

根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入,不需要输入属性名称或者属性类型。

一般不用

<?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标签属性autowire,配置自动装配
          autowire属性常用两个值:
              byName根据属性名称注入 ,注入值bean的id值和类属性名称一样
              byType根据属性类型注入
      -->
<!--    就是将Emp中的dept属性自动把id值为dept的bean标签对象自动注入 ,由于没有id值为name和gender的,因此该值为null

并且注入的Dept也是为空的-->
    <bean id="emp" class="com.lsy.autotest.Emp" autowire="byName"></bean>

<!--    按照属性的类型进行自动装配-->
    <bean id="emp" class="com.lsy.autotest.Emp" autowire="byType"></bean>
    <bean id="dept" class="com.lsy.autotest.Dept"></bean>
    
    
</beans>

8.IOC操作bean管理(引入外部属性文件)

1.数据库信息的配置

引入Druid的jar包;

方式一:直接配置

  <!--直接配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

方式二,引入外部属性文件文件配置数据库连接池

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值