06.XML形式实现IoC-尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)

P命名空间注入

  1. 添加xmlns约束

    xmlns:p="http://www.springframework.org/schema/p"
    
  2. 使用p命名空间进行属性注入bean9.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 ">  
        <!-- p命名空间,要引入xmlns:p="http://www.springframework.org/schema/p"      -->  
        <!-- 引入bean8对象   -->  
        <import resource="bean8.xml"/>  
        <bean name="studentp" class="NewStudent"  
        p:SName="李华" p:SNumber="114514" p:teacherMap-ref="teacherMap" p:lessons-ref="lessonList">  
        </bean></beans>
    
  3. 编写测试方法

    @Test  
    public void testPName() {  
        //加载spring配置文件  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean9.xml");  
        //获取bean  
        NewStudent Student = (NewStudent) applicationContext.getBean("studentp");  
        System.out.println(Student.toString());  
    }
    
  4. 输出

    NewStudent(sName=李华, sNumber=114514, teacherMap={1=Teacher(tName=李老师, tNumber=20000), 2=Teacher(tName=刘老师, tNumber=20001), 3=Teacher(tName=张老师, tNumber=20002)}, lessons=[Lesson(LName=数学), Lesson(LName=语文), Lesson(LName=英语)])
    

引入外部属性文件

  1. 引入数据库相关依赖

    <!--MySQL驱动-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
    </dependency>
    <!--数据源-->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.31</version>
    </dependency>
    
  2. 创建外部属性文件properties,定义数据信息

    jdbc.user=root  
    jdbc.password=root  
    jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC  
    jdbc.driver=com.mysql.cj.jdbc.Driver
    
  3. 创建spring配置文件,引入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/context  
    	http://www.springframework.org/schema/context/spring-context.xsd  
    	http://www.springframework.org/schema/beans  
    	http://www.springframework.org/schema/beans/spring-beans.xsd">  
    <!--引入外部属性文件-->  
    <context:property-placeholder location="classpath:jdbc.properties"/>  
    <!--完成数据库信息注入-->  
    <bean name="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">  
    	<property name="url" value="${jdbc.url}"/>  
    	<property name="username" value="${jdbc.user}"/>  
    	<property name="password" value="${jdbc.password}"/>  
    	<property name="driverClassName" value="${jdbc.driver}"/>  
    </bean></beans>
    
  4. 编写测试方法获取对象

    @Test  
    public void testJdbc(){  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-jdbc.xml");  
        DruidDataSource druidDataSource=(DruidDataSource)applicationContext.getBean("druidDataSource");  
        System.out.println("Url:"+druidDataSource.getUrl());  
        System.out.println("Username:"+druidDataSource.getUsername());  
        System.out.println("Password:"+druidDataSource.getPassword());  
        System.out.println("DriverClassName:"+druidDataSource.getDriverClassName());  
    

}
```

  1. 输出结果

    Url:jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
    Username:root
    Password:root
    DriverClassName:com.mysql.cj.jdbc.Driver
    

Bean的作用域

在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围

取值作用创建对象的时机
singleton这个bean的对象在IOC容器中始终为单实例1OC容器初始化时
prototype这个bean在IOC容器中有多个实例获取bean时

在WebApplicationContext环境下还会有另外几个作用域(但不常用)

取值作用
request在一个请求中有效
session在一个会话中有效
  1. 创建一个Order类,为了在sout对象时能输出对象的地址,不要重写toString()

    public class Order {  
    }
    
  2. 注入单例对象和多例对象11-bean-scope.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="order1" class="Order" scope="singleton"/>  
        <!-- 创建多例对象   -->  
        <bean id="order2" class="Order" scope="prototype"/>  
    </beans>
    
  3. 编写测试方法

    @Test  
    public void testScope(){  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("11-bean-scope.xml");  
        Order Order1_1=(Order)applicationContext.getBean("order1");  
        Order Order1_2=(Order)applicationContext.getBean("order1");  
        System.out.println("单例对象输出:");  
        System.out.println("Order1_1:"+Order1_1);  
        System.out.println("Order1_2:"+Order1_2);  
        Order Order2_1=(Order)applicationContext.getBean("order2");  
        Order Order2_2=(Order)applicationContext.getBean("order2");  
        System.out.println("多例对象输出:");  
        System.out.println("lesson2_1:"+Order2_1);  
        System.out.println("lesson2_2:"+Order2_2);  
    }
    
  4. 输出结果

    单例对象输出:
    Order1_1:Order@3738449f
    Order1_2:Order@3738449f
    多例对象输出:
    lesson2_1:Order@69e1dd28
    lesson2_2:Order@11bd0f3b
    

Bean生命周期

①具体的生命周期过程

  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean的后置处理器(初始化之前)
  • bean对象初始化(需在配置bean时指定初始化方法)
  • bean的后置处理器(初始化之后)
  • bean对象就绪可以使用
  • bean对象销毁(需在配置bean时指定销毁方法)
  • 1OC容器关闭
  1. 创建AnyClass类

    import lombok.Getter;  
    
    @Getter  
    public class AnyClass {  
        private String name;  
    
        void AnyClass(){  
            System.out.println("Bean对象创建,调用无参构造");  
        }  
        public void setName(String name) {  
            this.name = name;  
            System.out.println("Bean对象属性设置,调用setter");  
        }  
        public void initMethods(){  
            System.out.println("调用指定的初始化方法");  
        }  
        public void destroyMethods(){  
            System.out.println("调用指定的销毁方法");  
        }  
    }
    
  2. 创建MyBeanPost类,重写BeanPostProcessor的后置配置器方法

    import org.springframework.beans.factory.config.BeanPostProcessor;  
    
    public class MyBeanPost implements BeanPostProcessor {  
    
        //初始化之前执行  
        @Override  
        public Object postProcessBeforeInitialization(Object bean, String beanName) {  
            System.out.println("Bean后置处理器,初始化之前执行");  
            return bean;  
        }  
        //初始化之后执行  
        @Override  
        public Object postProcessAfterInitialization(Object bean, String beanName) {  
            System.out.println("Bean后置处理器,初始化之后执行");  
            return bean;  
        }  
    }
    
  3. 注入AnyClass类和MyBeanPost类

    <?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">  
        <!-- init-method:指定初始化方法   -->  
        <!-- destroy-method:指定销毁方法   -->  
        <bean id="anyCLass1" class="AnyClass" init-method="initMethods" destroy-method="destroyMethods">  
            <property name="name" value="ClassName"/>  
        </bean>    <!-- 后置处理器需要放入ioc才能生效   -->  
        <bean id="myBeanPost" class="MyBeanPost"/>  
    </beans>
    
  4. 编写测试方法

    @Test  
    public void testLifetime(){  
        //要调用销毁方法就不能使用ApplicationContext  
        ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("12-bean-lifetime.xml");  
        AnyClass anyClass=(AnyClass)classPathXmlApplicationContext.getBean("anyCLass1");  
        System.out.println("对象创建完成,可以使用:"+anyClass);  
        System.out.println("对象开始销毁");  
        classPathXmlApplicationContext.close();  
    }
    
  5. 输出:

    Bean对象属性设置,调用setter
    Bean后置处理器,初始化之前执行
    调用指定的初始化方法
    Bean后置处理器,初始化之后执行
    对象创建完成,可以使用:AnyClass@505fc5a4
    对象开始销毁
    调用指定的销毁方法
    
    

FactoryBean

FactoryBean,是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class,属性中配置的这个类的对象,而是getObject()方法的返回值。

通过这种机制,Sping可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只展示最简洁的使用界面。

在整合mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。

  1. 创建AnyClass类(上文已有)

  2. 创建MyFactoryBean类,继承BeanPostProcessor的后置配置器方法,重写必要方法

    import org.springframework.beans.factory.FactoryBean;  
    
    public class MyFactoryBean implements FactoryBean<AnyClass> {  
        @Override  
        public AnyClass getObject() throws Exception {  
            return new AnyClass();  
        }  
    
        @Override  
        public Class<?> getObjectType() {  
            return AnyClass.class;  
        }  
    }
    
  3. 注入MyFactoryBean类

    <?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="anyClass1" class="MyFactoryBean"/>  
    </beans>
    
  4. 编写测试方法

    @Test  
    public void testFactoryBean(){  
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("13-bean-factorybean.xml");  
        AnyClass anyClass=(AnyClass) applicationContext.getBean("anyClass1");  
        System.out.println(anyClass);  
    }
    
  5. 输出结果

    AnyClass@41e1e210
    

基于xml自动装配

创建一组MVC架构套件

dao.UserDao.java

package dao;  
  
public interface UserDao {  
    public void work();  
}

dao.UserDaoImpl.java

package dao;  
  
import lombok.Setter;  
  
@Setter  
public class UserDaoImpl implements UserDao{  
    @Override  
    public void work() {  
        System.out.println("UserDao-work");  
    }  
}

service.UserService.java

package service;  
  
public interface UserService {  
    public void Work();  
}

service.UserServiceImpl.java

package service;  
  
import dao.UserDao;  
import lombok.Setter;  
  
@Setter  
public class UserServiceImpl implements UserService{  
    private UserDao userDao;  
    @Override  
    public void Work() {  
        System.out.println("UserService-work");  
        userDao.work();  
    }  
}

controller.UserController.java

package controller;  
  
import lombok.Setter;  
import service.UserService;  
@Setter  
public class UserController {  
    private UserService userService;  
    public void work(){  
        System.out.println("UserController-work");  
        userService.Work();  
    }  
}

注入属性

<?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="userService" class="service.UserServiceImpl" autowire="byType"/>  
    <bean id="userController" class="controller.UserController" autowire="byType"/>  
    <bean id="userDao" class="dao.UserDaoImpl" autowire="byType"/>  
  
</beans>

编写测试方法

@Test  
public void testAutoWire() {  
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("auto-wire-bean.xml");  
    UserController userController=(UserController)applicationContext.getBean("userController",UserController.class);  
    userController.work();  
}

输出结果

UserController-work
UserService-work
UserDao-work

byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
若在IOC中,没有任何个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值null
若在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值