Spring:IoC容器(基于XML管理bean)

1. HelloWorld

三个步骤:

1.创建类

2.配置xml文件

3.通过xml文件使得bean实列化

1. 创建类 

package com.itgyl.bean;

public class HelloWorld {

    public HelloWorld() {
        System.out.println("1.通过无参构造创建对象");
    }

    public void hello() {
        System.out.println("hello world");
    }
}

2. 配置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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloWorld" class="com.itgyl.bean.HelloWorld"></bean>
    <!--如果对同一个类配置两次bean会报错:
    org.springframework.beans.factory.NoUniqueBeanDefinitionException:
     No qualifying bean of type 'com.itgyl.bean.HelloWorld' available:
     expected single matching bean but found 2: helloWorld,hello-->
    <!--<bean id="hello" class="com.itgyl.bean.HelloWorld"></bean>-->
</beans>

3. bean实例化

@Test
    public void testHello() {
        //1.配置xml配置信息

        //2.通过xml配置信息获取管理对象的IOC容器
        ApplicationContext ac =
                new ClassPathXmlApplicationContext("bean.xml");

        //3.通过bean.xml中的配置信息将类实例化
        HelloWorld hw = (HelloWorld) ac.getBean("helloWorld");

        System.out.print("2.配置信息创建对象:");
        hw.hello();

        logger.info("执行成功,打印日志");
    }

2. 实例化bean的三种方式

@Test
    public void testGetBean() {
        //通过xml获取管理对象IOC容器
        ApplicationContext ac =
                new ClassPathXmlApplicationContext("bean.xml");

        //1.通过id获取bean对象
        HelloWorld hw1 = (HelloWorld) ac.getBean("helloWorld");
        System.out.print("通过id获取bean实例化对象:");
        hw1.hello();

        //2.通过class类获取bean对象
        HelloWorld hw2 = ac.getBean(HelloWorld.class);
        System.out.print("通过class获取bean实例化对象");
        hw2.hello();

        //3.通过id和class类获取bean实例化对象
        HelloWorld hw3 = ac.getBean("helloWorld", HelloWorld.class);
        System.out.print("通过id和class获取bean实例化对象");
        hw3.hello();

    }

注意事项

当接口被多个bean实现时无法通过接口调用实例化bean的方法

package com.itgyl.bean;

public class StudentDao implements UserDao{
    @Override
    public void run() {
        System.out.println("student run");
    }
}
package com.itgyl.bean;

public class PersonDao implements UserDao{
    @Override
    public void run() {
        System.out.println("person run");
    }
}
@Test
    public void testDetail() {
        ApplicationContext ac =
                new ClassPathXmlApplicationContext("bean.xml");

        /***
         * 当接口只有唯一一个bean实现时可以通过接口调用bean的方法
         * 当接口被多个类同时实现时无法通过接口调用bean的方法,此时接口不知道调用哪个bean重写的方法
         */
        System.out.println("报错:一个接口被多个类同时实现无法通过接口调用方法,此时接口不知道调用哪个类的方法");
        UserDao ud = ac.getBean(UserDao.class);
        ud.run();

    }

如果组件类实现了接口,根据接口类型可以获取 bean 吗?

> 可以,前提是bean唯一

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?

> 不行,因为bean不唯一

3. bean属性值赋值方式

3.1 setter方式注入

<!--
1.set方式注入
property标签:通过set和get方法对对象进行属性赋值
name: 为对象的属性名
value:为对象的属性值
-->

此时会先通过无参构造创建实例化对象,再通过bean中的set方法进行赋值

<bean id="student1" class="com.itgyl.di.Student">
        <property name="studentName" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>

 3.2 constructor方式注入

<!--
2.constructor方式注入
constructor-arg标签:通过构造方法使对象实例化
可通过index:index下标从0开始,对应构造方法第一个属性,以此类推
可通过name:赋值可property一致
-->

 此时通过有参构造直接进行赋值,所有有参构造器必须实现

<bean id="student2" class="com.itgyl.di.Student">
        <constructor-arg name="studentName" value="lisi"></constructor-arg>
        <constructor-arg name="age" value="19"></constructor-arg>
    </bean>

 4. 特殊值处理方式

<!--
特殊值:
1.字面常量值:如10,20...
2.null值:通过null标签进行赋值
3.xml实体:在html中有些符号有特殊符号需要转义。如:尖括号<>:转移后&lt; h1 &gt
4.![CDATA[]]

2. null值需通过标签进行赋值,如果此时value="null"即赋值为字符串null而不是空值 

<bean id="student3" class="com.itgyl.di.Student">
        <property name="studentName"><null></null></property>
        <property name="age" value="18"></property>
    </bean>

 3.xml配置文件使用前端标签进行配置,有些符号有特殊含义,故需要通过转义字符进行转义

<bean id="student3" class="com.itgyl.di.Student">
        <property name="studentName" value="&lt; hello &gt;"></property>
    </bean>

4.通过 !CDATA[ 值 ]] 方式赋值

<bean id="student3" class="com.itgyl.di.Student">
        <property name="studentName">
            <value><![CDATA[ hello ]]></value>
        </property>

    </bean>

5. bean属性赋值

5.1 为bean属性为对象赋值

bean中有属性为对象时,若要为该属性赋值需通过ref进行引入,若直接通过value赋值会报错

定义两个类

public class Emp {
    private Dept dept;
    private String empName;
    private int id;
public class Dept {
    private String deptName;
    private int deptId;
    private List<Emp> list;

1. 外部引入bean 

<!--
    1.外部引入bean
    -->
    <bean id="dept1" class="com.itgyl.beandi.Dept">
        <!--注入普通属性值-->
        <property name="deptName" value="开发部"></property>
        <property name="deptId" value="10086"></property>
    </bean>

    <bean id="emp1" class="com.itgyl.beandi.Emp">
        <!--注入对象属性值,需要使用ref即从什么地方引用-->
        <property name="dept" ref="dept1"></property>
    </bean>

2. 内部引入bean

 <!--
    2.内部引入bean
    -->
    <bean id="emp2" class="com.itgyl.beandi.Emp">
        <!--注入对象属性值,内部引入-->
        <property name="dept">
            <bean class="com.itgyl.beandi.Dept" id="dept2">
                <property name="deptName" value="管理部"></property>
                <property name="deptId" value="10088"></property>
            </bean>
        </property>
        <!--注入普通属性值-->
        <property name="empName" value="张三"></property>
        <property name="id" value="007"></property>
    </bean>

3. 级联赋值

<!--
    3.级联赋值
    -->
    <bean class="com.itgyl.beandi.Dept" id="dept3">
        <property name="deptName" value="鸡术研发部"></property>
    </bean>

    <bean class="com.itgyl.beandi.Emp" id="emp3">
        <property name="empName" value="王五"></property>
        <!--级联赋值中先引入bean才能进行赋值-->
        <property name="dept" ref="dept3"></property>
        <property name="dept.deptName" value="技术研发部"></property>
    </bean>

 5.2 为bean属性为数组赋值

<!--给对象中的数组赋值-->
    <bean class="com.itgyl.beandi.People" id="people">
        <property name="hobby">
            <!--给数组赋值需要用到标签<array>-->
            <array>
                <value>吃饭</value>
                <value>睡觉</value>
                <value>打游戏</value>
            </array>
        </property>
    </bean>

5.3 为bean属性为集合赋值

5.3.1 为List集合赋值

public class Dept {
    private String deptName;
    private int deptId;
    private List<Emp> list;
<!--配置两个bean实例化对象-->
    <bean class="com.itgyl.beandi.Emp" id="emp1">
        <property name="empName" value="张三"></property>
        <property name="id" value="001"></property>
    </bean>
    <bean class="com.itgyl.beandi.Emp" id="emp2">
        <property name="empName" value="李四"></property>
        <property name="id" value="007"></property>
    </bean>

    <bean class="com.itgyl.beandi.Dept" id="dept">
        <!--注入集合:加上<list>标签即可,若集合中的值是对象,用ref引入对象即可,在通过bean指定具体的对象-->
        <property name="list">
            <list>
                <ref bean="emp1"></ref>
                <ref bean="emp2"></ref>
            </list>
        </property>
    </bean>

5.3.2 为Map集合赋值

public class Teacher {
    private String name;
    private Map<String, People> map;
<bean class="com.itgyl.beandi.People" id="people1">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
    </bean>
    <bean class="com.itgyl.beandi.People" id="people2">
        <property name="name" value="李四"></property>
        <property name="age" value="19"></property>
    </bean>
    <!--配置带有map的bean-->
    <bean class="com.itgyl.beandi.Teacher" id="teacher">
        <property name="name" value="仓老师"></property>
        <!--注入map数据需要用到<map>标签,在map标签中注入具体键值对用<entry>标签-->
        <property name="map">
            <map>
                <entry key="仓老师" value-ref="people1"></entry>
                <entry key="三上老师" value-ref="people2"></entry>
            </map>
        </property>
    </bean>

5.3.3 引用集合赋值

<?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:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--通过util:list可直接为集合注入值-->
    <util:list id="list">
        <ref bean="emp1"></ref>
        <ref bean="emp2"></ref>
    </util:list>

    <!--通过util:map可直接为集合注入值-->
    <util:map id="map">
        <entry key="仓老师" value-ref="emp1"></entry>
        <entry key="三上老师" value-ref="emp2"></entry>
    </util:map>

    <bean class="com.itgyl.beandi.ListMap" id="listMap">
        <!--上面已经定义了集合list和map此时通过引入直接将集合的属性值注入到该bean中,即完成集合属性注入-->
        <property name="list" ref="list"></property>
        <property name="map" ref="map"></property>
    </bean>

6. 命名空间

<!--
引入命名空间,即在xmls:名称="http://www.springframework.org/schema/名称"
可直接通过命名空间直接为bean注入属性值
-->
<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"
       
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.itgyl.beandi.Emp" id="emp1" p:empName="zhangsan" p:id="10096"></bean>
    <bean class="com.itgyl.beandi.Emp" id="emp2" p:empName="lisi" p:id="10011"></bean>
</beans>

7. 引入外部文件

通过location进行引入外部文件 

配置引入文件

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver
<?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">

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

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

8. bean的作用域

bean的作用域:
默认使用singleton,即在该IoC容器中该bean始终为单实例化,执行时机为IoC容器创建时
prototype,即在该IoC容器中有多个实例,执行时机为获取bean时
可通过scope进行配置
<bean class="com.itgyl.beandi.User" id="user" scope="singleton"
    init-method="initMethod" destroy-method="destroyMethod"></bean>

 9. bean的生命周期

<!--bean的生命周期:IoC容器关闭之前有效,bean的实例化默认是单实列singleton-->
<!--bean初始化的步骤
1.通过无参构造创建实例化对象
2.给bean设置属性值
3.bean调用后置处理器之前:调用初始化方法之前
4.调用intiMethod初始化方法
5.bean调用后置处理器之后:调用初始化方法之后
6.完成bean的实例化
7.bean调用destroyMethod销毁方法
8.IoC容器关闭-->
public class User implements BeanPostProcessor{
    private String name;
    private String password;

    private void destroyMethod() {
        System.out.println("7 bean实列销毁");
    }

    private void initMethod() {
        System.out.println("4 bean实列初始化");
    }

    public User() {
        System.out.println("1 bean通过无参构造进行初始化");
    }
public class myBeanProcess implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("3 bean后置处理器执行之前");
        System.out.println("☆☆☆" + beanName + " = " + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5 bean后置处理器执行之后");
        System.out.println("★★★" + beanName + " = " + bean);
        return bean;
    }
}
<bean class="com.itgyl.beandi.User" id="user" scope="singleton"
    init-method="initMethod" destroy-method="destroyMethod"></bean>

    <!--后置处理器不是对单独一个bean有效,对IoC容器所有的bean都生效-->
    <bean class="com.itgyl.beandi.myBeanProcess" id="myBeanProcess"></bean>

最终执行结果为1、2、3、4、5、6、7、8的打印语句

10. 基于XML自动装配 

 加入autowire配置

autowire=”byType"即通过类型自动装配

autowire="byName"即通过变量名进行自动装配,此时变量名为什么id名也必须保持一致

public class UserController {
    private UserService userService;

    public void setUserServiceImp(UserServiceImp userServiceImp) {
        this.userService = userServiceImp;
    }

    public void show() {
        userService.show();
    }
}
public class UserServiceImp implements UserService{
    private UserDaoImp userDaoImp;

    public void setUserDaoImp(UserDaoImp userDaoImp) {
        this.userDaoImp = userDaoImp;
    }

    @Override
    public void show() {
        userDaoImp.show();
    }
}
public class UserDaoImp implements UserDao{
    @Override
    public void show() {
        System.out.println("自动装配实现");
    }
}
<?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">

    <!--autowire自动装配根据类型自动进行属性注入-->
    <bean id="userController" class="com.itgyl.auto.controller.UserController" autowire="byType"></bean>
    <bean id="userServiceImp" class="com.itgyl.auto.service.UserServiceImp" autowire="byType"></bean>
    <bean id="userDaoImp" class="com.itgyl.auto.dao.UserDaoImp" autowire="byType"></bean>

</beans>
@Test
    public void testAuto() {
        //通过xml文件获取管理对象的IoC容器
        ApplicationContext context =
                new ClassPathXmlApplicationContext("auto.xml");

        UserController userController = context.getBean("userController", UserController.class);
        userController.show();
    }

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

食懵你啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值