1、什么是Bean管理

  1. Bean管理指的是两个操作
  2. Spring创建对象
  3. Spring注入属性

2、Bean管理操作有两种方式

  1. 基于xml配置文件方式实现
  2. 基于注解方式实现

IOC操作Bean管理(xml方式)

1、基于xml方式创建对象

image.png

  1. 在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
  2. 在bean标签有很多属性,介绍常用属性

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

    3.默认用无参数构造方法完成对象创建

2、基于xml注入属性

第一种方法:set方法进行注入

  • 对象需要生成set方法 ```java package com.daijunyi.model;

public class Book { private String name; private String author;

  1. public void setAuthor(String author) {
  2. this.author = author;
  3. }
  4. public void setName(String name) {
  5. this.name = name;
  6. }

}

通过xml配置注入属性
```xml
<bean id="book" class="com.daijunyi.model.Book">
        <property name="name" value="红领巾历险记"/>
        <property name="author" value="红领巾"/>
</bean>

第二种有参数构造方法进行注入。

  • 创建有参数构造函数的order类

    public class Order {
    
    private String orderId;
    
    private Integer number;
    
    public Order(String orderId, Integer number) {
       this.orderId = orderId;
       this.number = number;
    }
    }
    

    xml配置对象的创建

    <!-- 创建对象-->
    <bean id="order" class="com.daijunyi.model.Order">
       <!-- 有参数的构造函数-->
       <constructor-arg name="number" value="1"/>
       <constructor-arg name="orderId" value="1232qwd"/>
    </bean>
    

3、p名称空间注入

  1. p名称空间注入,可以用来简化xml配置

第一步 配置好xmlns:p的命名空间

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

xml文件中修改set的p命名空间的注入方式

    <!--用p命名空间方便 set方法的注入-->
    <bean id="book" class="com.daijunyi.model.Book" p:name="红领巾历险记" p:author="红领巾">
    </bean>

4、xml属性中注入其他类型的值

  1. null值:

     <!--用p命名空间方便 set方法的注入-->
     <bean id="book" class="com.daijunyi.model.Book" p:name="红领巾历险记" p:author="红领巾">
         <property name="page">
             <null></null>
         </property>
     </bean>
    
  2. 特殊符号:使用<!CDATA[具体内容]>写法可以写任何特殊符号

     <!--用p命名空间方便 set方法的注入-->
     <bean id="book" class="com.daijunyi.model.Book">
         <property name="author" value="红领巾"/>
         <!--特殊符号 <的写法等等,CDATA写法 <!DATA[具体内容]> -->
         <property name="name">
             <value><![CDATA[<红领巾历险记>]]></value>
         </property>
         <property name="page">
             <null></null>
         </property>
     </bean>
    

    5、属性中注入外部bean

  3. 创建两个类service类和dao类

  4. 在service类中添加dao类的成员变量,并设置set方法
  5. xml配置dao类的bean注入 核心点是xml中使用ref引用其他bean ```java package com.daijunyi.dao;

public interface UserDao {

public void doTest();

}

```java
package com.daijunyi.dao;

public class UserDaoImp implements UserDao {
    @Override
    public void doTest() {
        System.out.println("dao调用了");
    }
}
package com.daijunyi.service;

import com.daijunyi.dao.UserDao;

public class UserService {
    private UserDao dao;

    public void setDao(UserDao dao) {
        this.dao = dao;
    }

    public void doTest(){
        dao.doTest();
    }
}

配置xml文件

    <!--创建dao对象-->
    <bean id="userDao" class="com.daijunyi.dao.UserDaoImp"/>

    <!--创建service对象-->
    <bean id="userService" class="com.daijunyi.service.UserService">
        <!--注入dao对象-->
        <property name="dao" ref="userDao"/>
    </bean>

6、内部bean注入和级联赋值

1 内部bean注入:

  1. 创建一个员工类和部门类
  2. 在员工类中添加成员变量部门
  3. 配置xml进行属性注入,在property 中可以嵌套bean标签进行对象注入 ```java package com.daijunyi.model;

public class Dept { private String name;

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

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

}

```java
package com.daijunyi.model;

public class Emp {

    private String name;

    private Dept dept;

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

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

    @Override
    public String toString() {
        return "Emp{" +
                "name='" + name + '\'' +
                ", dept=" + dept +
                '}';
    }
}
    <bean id="emp" class="com.daijunyi.model.Emp">
        <property name="name" value="红领巾"/>
        <property name="dept">
            <bean id="dept" class="com.daijunyi.model.Dept">
                <property name="name" value="开发部"></property>
            </bean>
        </property>
    </bean>

2.级联赋值

    <!--级联赋值-->
    <bean id="emp" class="com.daijunyi.model.Emp">
        <property name="name" value="红领巾"/>
        <property name="dept" ref="dept"></property>
        <!--可以进行.的方式进行对象的调用,在进行属性的复制,前提是dept有get方法-->
        <property name="dept.name" value="女装部"></property>
    </bean>

    <bean id="dept" class="com.daijunyi.model.Dept">
        <property name="name" value="开发部"></property>
    </bean>

7、操作Bean管理注入集合属性

1.注入数组类型属性
2.注入List集合类型属性
3.注入Map集合类型属性

package com.daijunyi.model;

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

public class CollectionModel {

    private String[] courses;

    private List<String> list;

    private Map<String,String> maps;

    private Set<String> sets;

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

    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

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

    public void setCourses(String[] courses) {
        this.courses = courses;
    }
}
    <bean id="collectionModel" class="com.daijunyi.model.CollectionModel">
        <!--数组的注入方式-->
        <property name="courses">
            <array>
                <value>课程1</value>
                <value>课程2</value>
            </array>
        </property>
        <!--list的注入方式-->
        <property name="list">
            <list>
                <value>值1</value>
                <value>值2</value>
            </list>
        </property>
        <!--map的注入方式-->
        <property name="maps">
            <map>
                <entry key="ke1" value="value1"></entry>
                <entry key="key2" value="value2"></entry>
            </map>
        </property>
        <!--set的注入方式-->
        <property name="sets">
            <set>
                <value>set1</value>
                <value>set2</value>
            </set>
        </property>
    </bean>

8、在集合中注入对象

1.创建Course类
2.CollectionModel增加List属性courseList
3.配置xml

    <bean id="collectionModel" class="com.daijunyi.model.CollectionModel">
        <!--集合中对象注入-->
        <property name="courseList">
            <list>
                <ref bean="course"/>
                <bean id="course2" class="com.daijunyi.model.Course">
                    <property name="price" value="1201.1"/>
                    <property name="name" value="Mybatis"/>
                </bean>
            </list>
        </property>
    </bean>

    <bean id="course" class="com.daijunyi.model.Course">
        <property name="name" value="Spring5框架"/>
        <property name="price" value="100.1"/>
    </bean>

9、把集合注入抽取出来设置成公共部分

1.需要添加util命名空间
2.配置xml文件进行抽取

<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="collectionModel" class="com.daijunyi.model.CollectionModel">
        <!--集合中注入对象,并且采用引入抽取的方法引入-->
        <property name="courseList" ref="courseList"/>
    </bean>

    <bean id="course" class="com.daijunyi.model.Course">
        <property name="name" value="Spring5框架"/>
        <property name="price" value="100.1"/>
    </bean>
        <!--抽取的方法-->
    <util:list id="courseList">
        <ref bean="course"/>
        <bean id="course3" class="com.daijunyi.model.Course">
            <property name="price" value="1222.1"/>
            <property name="name" value="Mysql"/>
        </bean>
    </util:list>

10、操作Bean管理(FactoryBean)

1、Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)
2、普通bean:在配置文件中定义bean类型就是返回类型
3、工厂bean:在配置文件定义bean类型可以和返回类型不一样
第一步创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在方法中返回bean类型

package com.daijunyi.factorybean;

import com.daijunyi.model.Course;
import org.springframework.beans.factory.FactoryBean;

public class MyBean implements FactoryBean {

    //定义返回类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setName("Spring5");
        course.setPrice(11.1);
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return Course.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<?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.daijunyi.factorybean.MyBean">
    </bean>
</beans>

测试方法

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

        Object myBean = context.getBean("myBean");
        System.out.println(myBean.toString());
    }

输出结果

Course{name='Spring5', price=11.1}

Process finished with exit code 0

11、操作bean管理(bean作用域)

1、在Spring里面,设置创建bean实例是单例还是多实例
2、在Spring里面,默认情况下是单实例。

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

        Object myBean = context.getBean("sinTest");
        Object myBean2 = context.getBean("sinTest");
        System.out.println(myBean);
        System.out.println(myBean2);
    }

com.daijunyi.factorybean.SinTest@1a3869f4
com.daijunyi.factorybean.SinTest@1a3869f4

Process finished with exit code 0

设置多实例对象

<bean id="sinTest" class="com.daijunyi.factorybean.SinTest" scope="prototype"></bean>

scope值prototype和singleton

  • singleton(单实例)加载spring配置文件时候就会创建单实例对象
  • prototype(多实例)不是在加载spring配置文件时候创建对象,在调用getBean获取对象的时候才创建对象。每次都会创建一个。

12、操作Bean管理(生命周期)

12.1 bean生命周期

  1. 通过构造器创建bean实例(无参数构造)
  2. 为bean的属性设置值和对其他bean引用(调用set方法)
  3. 调用bean的初始化的方法(需要进行配置初始化的方法)
  4. bean可以使用了(对象获取到了)
  5. 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法) ```java package com.daijunyi.factorybean;

public class SinTest {

private String name;

public SinTest() {
    System.out.println("第一步构造函数执行");
}

public void setName(String name) {
    this.name = name;
    System.out.println("第二步设置属性");
}

public void initMethod(){
    System.out.println("第三步 初始化");
}

public void destroyMethod(){
    System.out.println("第五步 销毁方法");
}

}

测试代码
```java

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

        Object myBean = context.getBean("sinTest");
        System.out.println(myBean+"第四步获取对象操作");

        context.close();
    }

xml配置文件

    <bean id="sinTest" class="com.daijunyi.factorybean.SinTest" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="11"></property>
    </bean>

输出结果:

第一步构造函数执行
第二步设置属性
第三步 初始化
com.daijunyi.factorybean.SinTest@78ac1102第四步获取对象操作
第五步 销毁方法

Process finished with exit code 0

13、配置后置处理器

1、创建一个类实现接口BeanPostProcessor

package com.daijunyi.model;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class BeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("调用了postProcessAfterInitialization方法"+beanName);
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("调用了postProcessBeforeInitialization方法"+beanName);
        return bean;
    }
}

2、配置xml 添加bean

<bean id="beanPost" class="com.daijunyi.model.BeanPost"/>

这样每个bean实例就都会在初始化方法前后调用该方法了

调用了postProcessBeforeInitialization方法myBean
调用了postProcessAfterInitialization方法myBean
第一步构造函数执行
第二步设置属性
调用了postProcessBeforeInitialization方法sinTest
第三步 初始化
调用了postProcessAfterInitialization方法sinTest
com.daijunyi.factorybean.SinTest@a74868d第四步获取对象操作
第五步 销毁方法

Process finished with exit code 0

另外注意即使我们自己不配置nit-method也会调用这两个方法。

14、操作Bean管理(xml自动装配)

1、什么是自动装配
根据指定装配规则(属性名称)

2、演示,使用 autowire 来配置

  • 根据名称找 autowire=”byName”

    <!--根据名称自动注入 emp中的dept属性自动根据名称找到dept的bean-->
      <bean id="emp" class="com.daijunyi.model.Emp" autowire="byName">
          <property name="name" value="红领巾"/>
      </bean>
    
      <bean id="dept" class="com.daijunyi.model.Dept">
          <property name="name" value="研发部"/>
      </bean>
    
  • 根据类型找 autowire=”byType”

      <!--根据名称自动注入 emp中的dept属性自动根据类型找到dept的bean-->
      <bean id="emp" class="com.daijunyi.model.Emp" autowire="byType">
          <property name="name" value="红领巾"/>
      </bean>
    
      <bean id="dept" class="com.daijunyi.model.Dept">
          <property name="name" value="研发部"/>
      </bean>
    

    15、操作Bean管理(外部属性文件)

    1、直接配置数据库信息

    1、xml配置dataSource数据
    2、引入druid包和数据Driver包

      @Test
      public void poolTest(){
          ApplicationContext context = new ClassPathXmlApplicationContext("db.xml");
          try {
              DataSource dataSource = (DataSource) context.getBean("dataSource");
              Connection connection = dataSource.getConnection();
    
              String sql = "select * from tb_city";
              PreparedStatement preparedStatement = connection.prepareStatement(sql);
              ResultSet resultSet = preparedStatement.executeQuery();
              ResultSetMetaData metaData = preparedStatement.getMetaData();
              while (resultSet.next()){
                  for (int i=0;i<metaData.getColumnCount();i++){
                      Object object = resultSet.getObject(metaData.getColumnLabel(i+1));
                      System.out.println(object);
                  }
              }
          } catch (SQLException e) {
              e.printStackTrace();
          }
      }
    
    <?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="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/learn"/>
          <property name="username" value="root"/>
          <property name="password" value="qwerasdf123"/>
      </bean>
    </beans>
    

    2、配置外部文件

    1、创建外部文件jdbc.properties文件

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/learn
    username=root
    password=qwerasdf123
    

    2、配置xml context 名称空间

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

    3、xml文件中引入外部jdbc.properties文件

    <!--引入外部属性文件-->
      <context:property-placeholder location="classpath:jdbc.properties"/>
    

    4、使用${}语法把xml文件中的value值修改为这个语句中的 ```xml <?xml version=”1.0” encoding=”UTF-8”?>

<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</bean>

```