剖析spring IOC DI

本文深入探讨了Spring框架中的依赖注入(DI)和控制反转(IOC)概念,讲解了如何利用ClassPathXmlApplicationContext获取配置工厂环境,以及如何通过ApplicationContext接口进行bean的生产和属性赋值。同时,详细介绍了bean的生产、赋值、作用域和工厂Bean的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

在传统业务中我们会在service中调用

UserDao userDao = new UserDaoImpl();
这样我们的业务就会与dao的实现关联在了一起,当我们的组件需要增加或者修改时  怎么办呢?我们就会去 修改实现类增加实现类等操作  ,然后自己再new 一个impl来实现要求,
如果我们不再new UserDaoImpl()只是组装private UserDao userDao;并在业务里添加getter setter 或者构造器来接收一个对象就是spring里面的bean  并把创建bean的权利交给spring工厂就是容器IOC(此时我们不管对象的创建),我们只需要等待接收bean就可以   这就是依赖注入DI


### 核心组件
1:ClassPathXmlApplicationContext它用来获取配置工厂环境,此环境用来生产bean 并未我们的getter  constructor 的属性赋值
2:  ApplicationContext 是1的接口1实现了2
具体用法

1:用来获取环境就是开启工厂
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
2:获取生产的bean
AutoComonent autoComonent1 = (AutoComonent) context.getBean("auto");

核心配置文件applicationContext.cml

<?xml version="1.0" encoding="UTF-8"?>
<!--约束
        dtd约束:  xxx.dtd 用来约束文件的 标签  顺序  属性 格式等
        xsd约束:  xxx.xsd 用来约束文件的 标签  顺序  属性 格式等
-->
<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">
    <!-- 作用:声明需要spring 生产的组件 -->
    <!-- UserDAOImpl组件  id="组件标识" class="组件类型" -->
</beans>

生产不同数据类型并且赋值

普通bean的上产和赋值

生产一个 名为userBean的bean 并传给一个实现类的犬类路径名
为什么是实现累的全类路径名是因为 spring底层会通过
<bean class="xx.xx.xxx.XXX" id="xxx">
// 反射
String classpath="com.zhj.domain.User";
Class user = Class.forName(classpath);
Constructor constructor = user.getConstructor();
User o = (User)constructor.newInstance();
来创建出来我们需要的bean




<bean id="userBean" class="com.qf.dao.UserDaoImpl">
</bean>
<bean id="userService" class="com.qf.service.UserServiceImpl">
    <!--赋值给getter setter-->
    <!--普通bean用name属性注明bean标签中产生的bean的id ref用来引用-->
    <property name="userDao" ref="userBean"></property>
    <!--此处的userDao为serviceImpl里面组装的dao  就是等待依赖注入的那个-->
</bean>

<!--setter注入其他类型的的方式-->
<bean id="setDi01" class="com.qf.di.SetComponent">
    <!--数字用 value赋值-->
    <property name="id" value="2"></property>
    <property name="name" value="****"></property>
    <property name="gender" value="true"></property>
    <property name="userDao" ref="userBean"></property>

    <!--properties赋值-->
    <property name="prop">
        <props>
            <prop key="url">jdbc:mysql....</prop>
            <prop key="driver">com.mysql.jdbc.Driver</prop>
            <prop key="username">username</prop>
        </props>
    </property>
    <!--map赋值-->
    <property name="map">
        <map>
            <entry key="username" value="root"></entry>
            <entry key="password" value="123"></entry>
        </map>
    </property>
    <!--set-->
    <property name="set">
        <set>
            <value>张三</value>
            <value>李四</value>
            <value>张三</value>
                <!--此处与list不同list可以引入一个bean  set类型不可以引入`在这里插入代码片`-->
        </set>
    </property>
    <!--list-->
    <property name="list">
        <list>
            <value>flksdj</value>
            <ref bean="userBean"></ref>
        </list>
    </property>
</bean>



构造器注入方式
<!--构造器-->
<bean id="constructor" class="com.qf.di.ConsComponent" scope="prototype">
    <constructor-arg index="0" type="java.lang.Integer" value="32"></constructor-arg>
    <constructor-arg index="1" type="java.lang.String" value="hfh"></constructor-arg>
</bean>


bean的作用域单例:scope=“singleton”

他是默认的作用域 因为我们绝大部门用到的是默认的作用域无论你获取
getBean多少次他都是唯一的,而且spring会投入很大额经历都在管理他

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AutoComonent autoComonent1 = (AutoComonent) context.getBean("auto");
AutoComonent autoComonent2 = (AutoComonent) context.getBean("auto");
System.out.println("@@@@@@@@@@@@@"+autoComonent1);
System.out.println("$$$$$$$$$$$$"+autoComonent2);

输出结果:
@@@@@@@@@@@@@com.qf.di.AutoComonent@4eb7f003
$$$$$$$$$$$$com.qf.di.AutoComonent@4eb7f003
我们会发现hashCode一样说明此处两次获取的bean是同一个

bean的作用域多例: scope=“prototype”

我们可以手动修改bean 的作用域

<bean id="constructor" class="com.qf.di.ConsComponent" scope="prototype">
    <constructor-arg index="0" type="java.lang.Integer" value="32"></constructor-arg>
    <constructor-arg index="1" type="java.lang.String" value="hfh"></constructor-arg>
</bean>
运行结果

@@@@com.qf.di.ConsComponent@51c8530f
$$$$$$$$$$$$$$$$$$com.qf.di.ConsComponent@7403c468
此时hashCode不一样就说明此处获取到的两个bean并非同一个

多例spring工厂不会化太多精力去管理他因此他的存活期与工厂无关他在被调用时存活 而且他没有destroy期





工厂Bean

他用来生产那些复杂的bean,而且他只有这一个作用,而spring容器可以生产任意类型的bean,但是有一种类型她不适合他生产,就是复杂类型,
带环境配置的bean他spring容器生产出来的将会是一个空的bean没有实际作用例如SqlSessionFactory 因为Sql需要url driver username password 等环境
因此我们就需要工厂Bean来帮忙

public class MySqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>{
    // 主体逻辑  完成某种复杂对象的生产
    // 会在首次使用时调用
    public SqlSessionFactory getObject() throws Exception {
        System.out.println("MyFactoryBean create SqlSessionFactory~~~");
        // 构建过程
        Reader reader = Resources.getResourceAsReader("configuration.xml");
        return new SqlSessionFactoryBuilder().build(reader);
    }
    // 返回 某种复杂对象的 类对象
    @Override
    public Class<?> getObjectType() {
        return SqlSessionFactory.class;
    }
    // 控制复杂对象的创建模式
    @Override
    public boolean isSingleton() {
        return true;
    }
    public MySqlSessionFactoryBean() {
        System.out.println("mySqlSessionFactory Create~~~");
    }
}














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值