Spring源码级笔记(二)

3 IOC操作Bean管理(FactoryBean)

  1. spring有两种类型的Bean,一种普通的bean,另一种工厂bean(FactBean)
  2. 普通bean: 在配置文件中定义bean类型就是返回类型
  3. 工厂bean: 在配置文件定义bean类型可以和返回类型不一样
  • 第一步 创建类,让这个类为工厂bean,实现接口FactoryBean
  • 第二步 实现接口里面的方法 在实现的方法中定义返回bean的类型
package com.wjiangquan.spring5.factorybean;

import com.wjiangquan.spring5.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;

/**
 * @author weijiangquan
 * @date 2022/9/25 -18:40
 * @Description
 */
public class MyBean implements FactoryBean<Course> {
    /**
     * 定义返回的bean
     * @return
     * @throws Exception
     */
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("asda");
        return course;
    }


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

    @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.wjiangquan.spring5.factorybean.MyBean"></bean>
</beans>
package com.wjiangquan.spring5.testDemo;

import com.wjiangquan.spring5.collectiontype.Course;
import com.wjiangquan.spring5.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author weijiangquan
 * @date 2022/9/25 -18:44
 * @Description
 */
public class testBean {



    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Course myBean = context.getBean("myBean", Course.class);


        System.out.println(myBean);
    }
}

image-20220925185110606

注意,如果这个地方这样写将会发生错误

image-20220925185234320

大概的意思就是类型不匹配

4 bean的作用域

  1. 在Spring里面,可以设置成是单实例还是多实例,默认是单实例的

可以做一个简单的验证

多次获取

   @Test
    public void Bean1test(){
        ApplicationContext context = new  ClassPathXmlApplicationContext("bean1.xml");
        Book book = context.getBean("book", Book.class);
        Book book1 = context.getBean("book", Book.class);
        System.out.println("=================");
        System.out.println(book);
        System.out.println(book1);
        System.out.println("=====================");
        book.test();
    }

从结果可以看出来每次获取的对象都是一样的(所以默认是单实例的----不过自己可以在配置文件中进行修改)

image-20220925185903550

4.1 设置单实例,多实例

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

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

(2)scope 属性值

第一个值 默认值,singleton,表示是单实例对象

第二个值 prototype

在原来的基础上进行修改bean的文件之后

image-20220925190424324

再次测试的时候,发现

创建的对象不一样了,此时是多实例对象了

image-20220925190510324

singleton 和 prototype 区别:

第一 singleton 单实例,prototype 多实例

第二 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象

​ 设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象

注意初了上面的两种方式之外,还有requestsession两种,两种了解一下就可以了

5 bean的声明周期

1.生命周期

从对象的创建到对象的销毁的过程

2.bean的声明周期

(1) 通过构造器创建bean实例(无参构造)

(2) 为bean的属性设置值和对于其它bean的引用(调用set方法)

(3) 调用bean的初始化方法(需要进行配置)

(4) bean可以使用了(对象获取到了)

(5) 当容器关闭的时候,调用bean的销毁的方法

3.演示bean的生命周期

创建一个实例类Orders

package com.wjiangquan.spring5.bean;

/**
 * @author weijiangquan
 * @date 2022/9/25 -21:49
 * @Description
 */
public class Orders {

    //无参构造
    public Orders() {
        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("第五步 执行销毁的方法");
    }


}

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="orders" class="com.wjiangquan.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
		<property name="oname" value="手机"></property>
	</bean>


</beans>

测试代码的书写


    @Test
    public void testBean1(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步 获取bean的实例对象");
        System.out.println(orders);

        //手动让bean的实例进行销毁
        context.close();    //close在这个类中ClassPathXmlApplicationContext
    }
}

运行结果的检验,和预期的完全相符

image-20220925220329170

在上面的两步之上还有两步需要处理

5.bean的后置处理器

bean的声明周期添加之后就是7步,没有添加的就是五步

image-20220925220608463

image-20220925220616127

演示添加后置处理器的效果

(1) 创建类,实现接口BeanPostProcessor,创建后置处理器

创建一个类

package com.wjiangquan.spring5.bean;

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


/**
 * @author weijiangquan
 * @date 2022/9/25 -22:08
 * @Description
 */
public class MyBeanPost implements BeanPostProcessor{

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

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


    @Override
     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("再初始化之后执行的方法");
        return bean;
    }
}

在配置文件开启后置处理器

<?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="orders" class="com.wjiangquan.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
		<property name="oname" value="手机"></property>
	</bean>

	<!--配置后置处理器-->
	<bean id="myBeanPost" class="com.wjiangquan.spring5.bean.MyBeanPost"></bean>


</beans>

注意:对于上面的写法,将会为所有的bean都加上上后置处理器

image-20220925221858362

6 bean的管理xml方法–自动装配

注意在实际中使用xml注入的方式使用的很少,一般都是使用注解,但是还是有必要进行了解的

  1. 什么是自动装配

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

  2. 演示自动装配的过程

    创建了两个实体类

package com.wjiangquan.spring5.outowire;

/**
 * @author weijiangquan
 * @date 2022/9/25 -22:21
 * @Description
 */
public class Dept {

    @Override
    public String toString() {
        return "Dept{}";
    }
}

package com.wjiangquan.spring5.outowire;

/**
 * @author weijiangquan
 * @date 2022/9/25 -22:21
 * @Description
 */
//员工
public class Emp {
    private Dept dept;

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

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

    public void test(){
        System.out.println(dept);
    }
}

配置文件

<?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标签属性autowire, 配置自动装配
	autowire属性常用的两个值:
	byName根据属性名称注入,注入值bean的id和类属性名称一样
	byTYpe根据属性类型进行注入-->
	<bean id="emp" class="com.wjiangquan.spring5.outowire.Emp" autowire="byName">
		<!--下面是手动的写法-->
		<!--<property name="dept" ref="dept"></property>-->
	</bean>


	<bean id="dept" class="com.wjiangquan.spring5.outowire.Dept">

	</bean>


</beans>

需要的注意的是

image-20220925223851158

7 引入外部的属性文件

当属性有许多的时候,全部写的就会比较麻烦,本节主要用于处理该问题

1.直接配置数据库的信息

(1) 配置德鲁伊连接池

(2) 引入德鲁伊的jar包

image-20220925225128863

	<!--直接配置连接池 -->
	<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="123456"></property>
	</bean>

2、引入外部属性文件配置数据库连接池

(1)创建外部属性文件,properties 格式文件,写数据库信息

image-20220925225602708

(2)把外部 properties 属性文件引入到 spring 配置文件中

  • 引入 context 名称空间

    红框部分为新添加的部分

image-20220925225815474

  • 在 spring 配置文件使用标签引入外部属性文件
<!--引入外部的属性文件-->
	<context:property-placeholder location="classpath*:jdbc.properties"/>
	<!--直接配置连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${prop.driverClass}"></property>
		<property name="url" value="${prop.url]"></property>
		<property name="username" value="${prop.userName}"></property>
		<property name="password" value="${prop.password]"></property>
	</bean>
  • 在 spring 配置文件使用标签引入外部属性文件
<!--引入外部的属性文件-->
	<context:property-placeholder location="classpath*:jdbc.properties"/>
	<!--直接配置连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${prop.driverClass}"></property>
		<property name="url" value="${prop.url]"></property>
		<property name="username" value="${prop.userName}"></property>
		<property name="password" value="${prop.password]"></property>
	</bean>
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莪假裝堅強

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值