首页 专题 文章 代码 归档
bean的一些处理
2020.01.23 09:55 2020.01.23 09:55

bean的一些处理东西

本节我们要讲一下在bean的一些额外配置以及一些额外处理等等的东西。

util名称空间

作用是创建集合类型的bean,方便他人的引用!

1、加入util名称空间

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

2、使用

<util:map id="misiai_map">
    <!--一个entry就代表一个键值对-->
    <entry key="key01" value="迷思爱"/>
    <entry key="key02" value="学习乐园"/>
    <!--引用外部的bean 的 id-->
    <entry key="key03" value-ref="book01"/>
    <!--内部bean-->
    <entry key="key04">
        <bean class="com.misiai.bean.Car">
            <property name="name" value="奔驰"/>
            <property name="color" value="银色"/>
        </bean>
    </entry>
</util:map>

<bean id="student03" class="com.misiai.bean.Student">
    <property name="map" ref="misiai_map"/>
</bean>

3、测试

@Test
public void test03() {
    Student student03 = ap.getBean("student03", Student.class);
    System.out.println(student03.getMap());
}

截图-1579672598

Tips:

上面我们只是举了map的例子,其实util还有其他许多的类型:

截图-1579672706

级联属性

<bean id="student04" class="com.misiai.bean.Student">
    <!--引用赋值的时候,顺带改变car的价格-->
    <property name="car" ref="car"/>
    <property name="car.price" value="50000"/>
</bean>
@Test
public void test04() {
    Student student04 = ap.getBean("student04", Student.class);
    System.out.println(student04.getCar());
}

结果:

截图-1579672895

但是,由于是引用,那么原来的bean的值可能被覆盖:

@Test
public void test04() {
    Student student04 = ap.getBean("student04", Student.class);
    Car car = ap.getBean("car", Car.class);
    System.out.println(car.getPrice());
    System.out.println(student04.getCar());
}

截图-1579673001

Bean信息的重用

通过parent来引用父级的bean的一些信息:

<!--bean信息的重用-->
<bean id="student05" class="com.misiai.bean.Student">
    <property name="name" value="Misiai"/>
    <property name="sno" value="10003"/>
</bean>
<bean id="student06" class="com.misiai.bean.Student" parent="student05">
<!--parent代表要继承的Bean的信息-->
    <property name="sno" value="10004"/>
    <!--要改变的就还是在这里填写,不改的就忽略!-->
</bean>

测试:

@Test
public void test05() {
    Student student05 = ap.getBean("student05", Student.class);
    Student student06 = ap.getBean("student06", Student.class);
    System.out.println(student05);
    System.out.println("student06 = " + student06);
}

结果:

截图-1579673361

学号改了,姓名没改!


我们还可以为一个bean设置abstract="true"属性,代表该bean只能被继承,不能被使用!

<!--bean信息的重用-->
<bean id="student05" class="com.misiai.bean.Student" abstract="true">
    <property name="name" value="Misiai"/>
    <property name="sno" value="10003"/>
</bean>

如果加了abstract,那么还尝试获取的话,就会有异常:

org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'student05': Bean definition is abstract

bean之间的依赖

A. 默认

这里我们新建spring-ioc-3.xml配置文件,新建三个bean:

<bean id="student01" class="com.misiai.bean.Student">

</bean>
<bean id="car01" class="com.misiai.bean.Car">

</bean>
<bean id="book01" class="com.misiai.bean.Book">

</bean>

也新建一个测试类,Test03.java

在三个实体类的无参构造器中,各打印一句话:XX被创建了!

测试:

@Test
public void test01() {
    Student student = (Student) ap.getBean("student01");
    Car car01 = ap.getBean("car01", Car.class);
    Book book01 = ap.getBean("book01", Book.class);

}

看其先后顺序:

截图-1579686808

结论:

按照配置的顺序创建的!

B. 有依赖(改变顺序)

<bean id="student01" class="com.misiai.bean.Student" depends-on="car01,book01">

</bean>
<bean id="car01" class="com.misiai.bean.Car">

</bean>
<bean id="book01" class="com.misiai.bean.Book">

</bean>

使用depends-on,添加依赖,多个依赖英文,分割,传入的是其他 bean的id

结果:

截图-1579687018

创建单实例和多实例*

bean的默认是单实例的,我们可以为bean标签添加一个scope属性,其值代表是单实例还是多实例。

可取的值:

  • prototype,多实例
    • 容器启动时,不创建
    • 获取的时候再创建,且创建的是新的
  • singleton,单实例(默认)
    • 在容器启动之前,则已经被创建了
    • 任何时候的获取都是获取之前创建好了的
  • request,web环境下,同一次请求创建一个bean(真实环境中,基本不用)
  • session,web环境下,同一次会话创建一个bean(真实环境中,基本不用)

测试:给car加一个prototype

<bean id="car01" class="com.misiai.bean.Car" scope="prototype">

</bean>
@Test
public void test01() {
    // Student student = (Student) ap.getBean("student01");
    // Book book01 = ap.getBean("book01", Book.class);
    Car car01 = ap.getBean("car01", Car.class);
    Car car02 = ap.getBean("car01", Car.class);
    System.out.println(car01 == car02);

}

结果:

截图-1579690505

创建有生命周期的bean

1、修改Book实体类,增加两个方法

public void myInit() {
    System.out.println("Book的初始化方法");
}

public void myDestroy() {
    System.out.println("Book的销毁方法");
}

2、修改配置 文件

<bean id="book01" class="com.misiai.bean.Book"
init-method="myInit" destroy-method="myDestroy">

</bean>

在标签中使用init-methoddestroy-method属性,属性值就是刚才新建的方法名。

3、测试

public class Test04 {
    ApplicationContext ap = new ClassPathXmlApplicationContext("spring-ioc-4.xml");

    @Test
    public void test01() {
        // Book book01 = ap.getBean("book01", Book.class);
        // System.out.println(book01);
    }
}

这里我们什么都不做,然后只是创建了容器,运行结果:

截图-1579690939

结论:只是执行了初始化方法(说明容器未销毁)

4、测试2

我们使用另一个Context对象,来测试(该对象有容器的close方法)

public class Test04 {
    ConfigurableApplicationContext ap = new ClassPathXmlApplicationContext("spring-ioc-4.xml");

    @Test
    public void test01() {
        ap.close();
    }
}

结果:

截图-1579691053

Bean的后置处理器

1、实现PostProcessor类

MyBeanPostProcessor.java

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

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "Processor之前");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "Processor之前");
        return bean;
    }
}

2、将此类定义到一个Bean中

<bean id="book01" class="com.misiai.bean.Book"
      init-method="myInit" destroy-method="myDestroy">
</bean>
<bean class="com.misiai.bean.MyBeanPostProcessor" id="beanPostProcessor"/>

3、测试

/**
 * 测试后置处理器
 */
@Test
public void test03() {
    Book book01 = ap.getBean("book01", Book.class);

}

结果:

截图-1579691715

结论:在某个类的初始化之前执行一次,之后执行一次。

那我们可以调用该处理器执行一些动作!

其具体流程:

容器启动 --- 后置处理器Before --- bean的初始化方法 --- 后置处理器After --- bean初始化完成

引用外部属性文件*

在某些地方,单实例是非常最重要的!比如:数据库的连接池

这里来讲一下如何使用spring管理我们的数据库连接池!

1、导包

A. durid:https://mvnrepository.com/artifact/com.alibaba/druid/1.1.21

可自行从上面链接下载 jar包!

截图-1579692453

2、新建配置文件

<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="url" value="jdbc:mysql://localhost:3306/java_test"/>

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="5"/>
    <property name="minIdle" value="5"/>
    <property name="maxActive" value="100"/>
</bean>

3、新建测试类

public class Test05 {
    ConfigurableApplicationContext ap = new ClassPathXmlApplicationContext("spring-ioc-5.xml");

    /**
     * 测试数据库
     */
    @Test
    public void test01() throws SQLException {
        // 1、从容器中拿到连接池
        DataSource dataSource = ap.getBean("dataSource", DataSource.class);
        System.out.println(dataSource);

    }
}

结果:

截图-1579693629

连接成功,我们这里就使用spring帮我们管理数据库连接池,然后数据库连接池使用的是druid(阿里开源维护的)!

但是有个问题,连接信息我们是写死了在xml配置文件里面的,那么如何写到外部呢?

步骤1:

新建jdbc.properties文件

jdbc.url=jdbc:mysql://localhost:3306/java_test
jdbc.username=root
jdbc.password=root
jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=100

步骤2:使用PropertyPlaceholderConfigurer类,引入jdbc.properties文件,然后在需要的地方使用${jdbc.username}获取

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="location" value="classpath:jdbc.properties"/>
</bean>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="url" value="${jdbc.url}"/>

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="${jdbc.initialSize}"/>
    <property name="minIdle" value="${jdbc.minIdle}"/>
    <property name="maxActive" value="${jdbc.maxActive}"/>
</bean>

结果没问题!

本节阅读完毕! (分享
二维码图片 扫描关注我们哟