Spring IOC 练习

Stella981
• 阅读 663

练习题
实验一 | 通过IOC容器创建对象,并为属性赋值
实验二 | 通过Bean的类型从IOC中获取bean的实例
实验三
3.1使用构造器在IOC中创建bean
3.2通过p名称空间为bean赋值
实验四
4.1正确的为各种属性赋值 测试使用nu11值、 引用类型赋值(引用其他bean、引用内部bean) 集合类型赋值(List、Map、 Properties)
4.2 Util名称空间创建集合类型的bean
4.3级联属性赋值
实验五 | 通过继承实现配置信息的重用
实验六 | 通过abstract属性创建一个模板bean
实验七 | Bean之间的依赖
实验八 | 测试bean的作用域
★实验九
实验十 | 创建带有生命周期方法的bean
实验十一 | 测试bean的后置处理器
★实验十二 | 引用外部属性文件(spring管理连接池)
实验十三 | 基于XML的自动装配(自动赋值)
实验十四 SPEL测试
★实验十五 | 使用注解分别创建Dao,Service,Controller
实验十六 | 指定扫描时不包含的类
实验十七 | 指定扫描时要包含的类
★实验十八 | 使用@Autowired注解实现根据类型的自动装配
★实验十九 | 资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean
★实验二十 | 使用@Qualifier注解明确指定目标bean的id
★实验二十一 | 在方法的形参上使用@Qualifier注解
★实验二十二 | @Autowired注解的required属性指定某个属性允许不被设置

TOC

练习题

实验一 | 通过IOC容器创建对象,并为属性赋值


ico.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="person01" class="per.wzy.spring.Person">
        <property name="age" value="18"></property>
        <property name="name" value="张三"></property>
        <property name="sex" value="男"></property>
    </bean>
</beans>

test.java

public class ioctest {
    @Test
    public void Test(){

        //创建容器对象
        //容器中的对象在容器创建完成的时候就已经创建好了(所有的对象都会创建)
        //同一组件在IOC中是单实例的
        ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");

        //获取对象
        Person person01 = (Person) context.getBean("person01");

        System.out.println(person01.getName());

    }
}

实验二 | 通过Bean的类型从IOC中获取bean的实例


//如果IOC容器中这个类型的bean有多个,则查找会报错
Person person = context.getBean(Person.class);
//存在多个同类型bean,根据id查找
Person person = context.getBean("person02",Person.class);

实验三

3.1使用构造器在IOC中创建bean

    <bean id="person03" class="per.wzy.spring.Person">
        <constructor-arg name="name" value="大花"></constructor-arg>
        <constructor-arg name="age" value="19"></constructor-arg>
        <constructor-arg name="sex" value="女"></constructor-arg>
    </bean>
  • 不添加name属性,默认按照构造器中属性顺序赋值
  • 添加index属性,设置位置
  • 添加type属性,设置值的类型,适用于构造器重载的情况

3.2通过p名称空间为bean赋值

  1. 引入p名称空间:beans中添加 xmlns:p="http://www.springframework.org/schema/p"

  2. 使用p名称空间进行赋值

    <bean id="person05" class="per.wzy.spring.Person"
           p:age="15" p:name="二花" p:sex="母猪">
       </bean>
    

实验四

4.1正确的为各种属性赋值 测试使用nu11值、 引用类型赋值(引用其他bean、引用内部bean) 集合类型赋值(List、Map、 Properties)

    **复杂属性赋值**


<bean id="person06" class="per.wzy.spring.Person">
        <constructor-arg name="age" value="16"></constructor-arg>
        <!--地址引用 bean-->
        <!--<constructor-arg name="child" ref="chid01"></constructor-arg>-->
        <constructor-arg name="child">
            <!--对象使用bean标签进行创建-->
            <bean class="per.wzy.spring.Children">
                <property name="sex" value="女"></property>
                <property name="name" value="翠花"></property>
                <property name="age" value="2"></property>
            </bean>
        </constructor-arg>
        <constructor-arg name="childrens">
            <list>
                <bean id="child02" class="per.wzy.spring.Children" p:sex="男" p:name="王五" p:age="18"></bean>
                <ref bean="chid01"></ref>
            </list>
        </constructor-arg>
        <constructor-arg name="name" value="三花"></constructor-arg>
        <constructor-arg name="sex" value="女"></constructor-arg>

        <!--MAP属性赋值-->
        <constructor-arg name="map">
            <map>
                <entry key="key01">
                    <bean class="per.wzy.spring.Children" p:age="18" p:name="华盛顿" p:sex="男"></bean>
                </entry>
            </map>
        </constructor-arg>
        <constructor-arg name="properties">
           <props>
               <prop key="username">wzy</prop>
               <prop key="pwd">123456</prop>
           </props>
        </constructor-arg>
    </bean>
  • 赋NULL值,不填写value属性,添加标签
  • 复杂属性赋值均不在value中进行赋值
  • List赋值:添加标签,标签中继续添加其他标签

4.2 Util名称空间创建集合类型的bean

  •   <!--添加命名空间导入提示 -->
      xmlns:context="http://www.springframework.org/schema/context
    
  • 导入util命名空间

  •   <util:map id="map01">    <entry key="key001">        <bean class="per.wzy.spring.Children">            <!--<constructor-arg name="age" value="15"></constructor-arg>-->            <!--<constructor-arg name="name" value="函数"></constructor-arg>-->            <!--<constructor-arg name="sex" value="男"></constructor-arg>-->            <property name="name" value="111"></property>            <property name="sex" value="男"></property>            <property name="age" value="150"></property>         </bean>    </entry></util:map>
    

4.3级联属性赋值

级联属性:属性的属性


    <bean name="person07" class="per.wzy.spring.Person">
        <property name="child" ref="chid01"></property>
        <property name="child.age" value="20"></property>
    </bean>

引用会更改原来bean中的值

实验五 | 通过继承实现配置信息的重用


parent:指定当前bean的配置信息继承于哪个bean

<bean name="person08" class="per.wzy.spring.Person" parent="person06">    <property name="name" value="哈子"></property></bean>

实验六 | 通过abstract属性创建一个模板bean


abstract="true" :这个bean的配置是抽象的,不能获取他的实例,只能用来被继承。

<bean name="person08" class="per.wzy.spring.Person" abstract="true">    <property name="name" value="继承"></property>    <property name="age" value="11"></property>    <property name="sex" value="男"></property></bean>

实验七 | Bean之间的依赖


  • 原本是按照bean的配置顺序创建
  • 使用depends-on决定创建顺序

实验八 | 测试bean的作用域

测试bean的作用域,分别创建单实例和多实例的bean


bean的作用域:指定bean是否单实例,xxx;默认:单实例的
prototype:多实例的
1)、容器启动默认不会去创建多实例bean
2)、获取的时候创建这个bean,每次获取创建一个新的

sing1eton:单实例的;默认的
1)、在容器启动完成之前就已经创建好对象,保存在容器中了。
2)、任何获取都是获取之前创建好的那个对象

★实验九

配置通过静态工厂方法创建的bean,实例工厂方法创建的bean、FactoryBean


bean的创建默认就是框架利用反射new出来的bean实例

<!--1、静态工厂(不需要创建工厂本身) Factory- method=" getAirP1ane"
指定哪个方法是工厂方法
class:指定静态工厂全类名
factory- method:指定工厂方法

package per.wzy.factory;
import per.wzy.spring.Car;

public class CarStaticFactory {
    public static Car getCar(String name){
        Car car = new Car();
        car.setName(name);
        car.setColor("Red");
        car.setPrice(95650.5);
        return  car;
    }
}

<bean name="car01" class="per.wzy.factory.CarStaticFactory" factory-method="getCar">
        <constructor-arg name="name" value="崩瓷"></constructor-arg>
    </bean>

实例工厂方法创建bean对象

<!--配置实例工厂-->
    <bean name="CarInterFace" class="per.wzy.factory.CarInterfaceFactory"></bean>

    <!--使用实例工厂创建bean对象-->
    <!--使用 constructor-arg 给工厂方法负责-->
    <bean name="car02" class="per.wzy.spring.Car" factory-bean="CarInterFace" factory-method="getCar">
        <constructor-arg name="name" value="奥迪"></constructor-arg>
    </bean>

实验十 | 创建带有生命周期方法的bean

package per.wzy.spring;

public class Book {

    private String bookname;
    private String isbn;
    private double price;

    //自定义初始化方法,不能带有参数,但可以抛出任意异常
    public void Init(){
        System.out.println(" book init ......");
    }

    //销毁方法
    public void Destory(){
        System.out.println("book destory ......");
    }

    public Book() {
    }

    public Book(String bookname, String isbn, double price) {
        this.bookname = bookname;
        this.isbn = isbn;
        this.price = price;
    }

    public String getBookname() {
        return bookname;
    }

    public void setBookname(String bookname) {
        this.bookname = bookname;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}


    <!--单实例bean:容器启动时自动创建-->
    <!--多实例bean: 容器启动时不会被创建,获取时创建-->
    <!--为bean自定义一些生命周期方法,创建或销毁时会使用这些方法-->
    <bean id="book01" class="per.wzy.spring.Book"
    destroy-method="Destory"
    init-method="Init">
        <property name="bookname" value="Java编程"></property>
        <property name="isbn" value="ki154454"></property>
        <property name="price" value="15.3"></property>
    </bean>

实验十一 | 测试bean的后置处理器

无论bean是否具有初始化方法,后置处理器都会执行

流程:

  • 编写后置处理器实现类

    package per.wzy.spring;

    import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"即将初始化");
        return bean;
    }
    
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"初始化完成");
        return bean;
    }
    

    }

  • 后置处理器注册在配置文件中

输出结果:

八月 31, 2019 4:06:46 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5cbc508c: startup date [Sat Aug 31 16:06:46 CST 2019]; root of context hierarchy
八月 31, 2019 4:06:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
book01即将初始化
book init ......
book01初始化完成
八月 31, 2019 4:06:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5cbc508c: startup date [Sat Aug 31 16:06:46 CST 2019]; root of context hierarchy
book destory ......

★实验十二 | 引用外部属性文件(spring管理连接池)

context命名空间

xmlns:context="http://www.springframework.org/schema/context"
````

xsi中添加

```xml
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd

外部配置文件

user=root
password=www123
jdbcUrl=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver

<!--引用外部属性文件,依赖context名称空间-->
<!--classpath:应用类路径下资源-->
<context:property-placeholder location="dbconfig.properties"></context:property-placeholder>
<!--引用外部属性文件(spring管理连接池)-->
<!--  ${key}  动态取出配置文件中键对应的值 -->
<!--username 是spring中的关键字,key不能设为username-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
    <property name="driverClass" value="${driverClass}"></property>
</bean>

实验十三 | 基于XML的自动装配(自动赋值)

自动装配《仅对自定义类型的属性有效,基本类型无法赋值
autowire="default/no" 不自动装配,默认情况
autowire="byName" 按照名字寻找,以属性名作为id去容器中找到组件,并赋值。找不到则为null
autowire="byType" 以类型作为依据去容器中查找组件,若不唯一则产生错误。若没找到对应,装配null
autowire="constructor"
按构造器进行赋值
1)、先按照有参构造器的参数类型进行匹配(成功赋值),不成功则赋值null
2)、如果按照类型找到了多个;以参数名作为id进行匹配,找到赋值,找不到则赋值null
3)、不会产生报错

<bean id="person01" class="per.wzy.spring.Person" autowire="constructor"></bean>

实验十四 SPEL测试

  • 在SpEL中使用字面量

  • 引用其他bean

  • 引用其他bean的某个属性值

  • 调用静态方法 #{T(全类名).静态方法名}

  • 调用非静态方法

    <bean id="person02" class="per.wzy.spring.Person">
        <property name="book" value="#{book01}"></property>
        <!--调用静态方法-->
        <property name="name" value="#{T(java.util.UUID).randomUUID().toString()}"></property>
        <!--调用非静态方法-->
        <property name="age" value="#{person01.getAge()}"></property>
    </bean>
    

★实验十五 | 使用注解分别创建Dao,Service,Controller

某个类上添加上任何一个注解都能快速的将这个组件加入到ioc容器的管理中
Spring有四个注解
@Controller:控制器;我们推荐给控制器层(serv1et包下的这些)的组件加这个注解
@Service:业务逻辑;我们推荐业务逻辑层的组件添加这个注解; Bookservice
@Repository:给数据库层(持久化层,dao层)的组件添加这个注解
@Component:给不属于以上几层的组件添加这个注解

注解可以随意添加。spring底层不会验证该组件

步骤:

  1. 给要添加的组件上添加上述四个注解的一个

  2. 告诉Spring,自动扫描添加了注解的组件,依赖context名称空间

  3. 一定要导入aop包(支持注解模式)

    <context:component-scan base-package="per.wzy">

使用注解加入到容器中的组件,和使用配置加入到容器中的组件行为都是默认一样的;
1、组件的id。默认就是组件的类名首字母小写
2、组件的作用域,默认就是单例的;

public class SpringTest {

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml");

    @Test
    public void test(){
        Object booksql = applicationContext.getBean("bookSql");
        Object booksql1 = applicationContext.getBean("bookSql");

        System.out.println(booksql==booksql1);  //true

}

注解后课添加(”XXX“)更改默认名称 || @Repository("bok")

添加Scope注解更改单/多实例 || @Scope(value = "prototype")

实验十六 | 指定扫描时不包含的类

<context:component-scan base-package="per.wzy">
           <!--通过注解判断是否添加进容器,指定注解不添加包含此注解的类-->
           <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
           <!--通过类指定不添加到容器中-->
           <context:exclude-filter type="assignable" expression="per.wzy.service.BookService"></context:exclude-filter>
       </context:component-scan>

实验十七 | 指定扫描时要包含的类

必须禁用默认的扫描规则

       <context:component-scan base-package="per.wzy" use-default-filters="false">
           <!-- use-default-filters="false" 禁用默认的扫描规则-->
           <context:include-filter type="assignable" expression="per.wzy.service.BookService"></context:include-filter>
       </context:component-scan>

★实验十八 | 使用@Autowired注解实现根据类型的自动装配

bookSql.java

@Repository
public class bookSql {

    public void bookSave(){
        System.out.println("svae book....");
    }
}

BookService.java

@Service
public class BookService {

   @Autowired
   private bookSql bsql; //自动装配

   public void bookAdd(){
      bsql.bookSave();
   }
}

BookServlet.java

@Controller
public class BookServlet {

    @Autowired
    private BookService service;

    public void get(){
        service.bookAdd();
    }
}

测试方法

public class SpringTest {

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml");

    @Test
    public void test(){
        BookServlet bean = applicationContext.getBean(BookServlet.class);
        bean.get();

    }
}

输出:

svae book....

★实验十九 | 资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean

@Autiwired 原理

  1. 先按照类型去容器中寻找对应的组件

  2. 找到一个,进行赋值

  3. 没有找到,抛出异常

  4. 找到多个,按照变量名作为id继续匹配。若没有对应匹配,报错

    • 原因(依据变量名进行匹配)
    • 解决:使用@Qualifier(value = "bookService")指定字符串作为id

    @Controller public class BookServlet {

    @Qualifier(value = "bookService")
    @Autowired
    private BookService service2;
    
    public void get(){
        service2.bookAdd();
    }
    

    }

★实验二十 | 使用@Qualifier注解明确指定目标bean的id

使用@Qualifier(value = "bookService")指定字符串作为id

@Controller
public class BookServlet {

    @Qualifier(value = "bookService")
    @Autowired
    private BookService service2;

    public void get(){
        service2.bookAdd();
    }
}

★实验二十一 | 在方法的形参上使用@Qualifier注解

/**
     * 方法上有autowired注解
     * 1.该方法会在bean创建时自动运行
     * 2.这个方法上的每一个参数都会自动注入值
     * @param service
     * @param bookSqls
     */
    @Autowired
    public void limengkeShabi(BookService service, @Qualifier(value = "bookSql") bookSql bookSqls){
        System.out.println("BookService:"+service+"   bookSql:"+bookSqls);
    }

★实验二十二 | @Autowired注解的required属性指定某个属性允许不被设置

@Controller
public class BookServlet {

    @Qualifier(value = "bookService")
    @Autowired(required = false)
    private BookService service3;

    public void get(){
        System.out.println("services3....."+service3);
//        service3.bookAdd();
    }
}

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

======

来自为知笔记(Wiz)

======

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Easter79 Easter79
2年前
Spring表达式语言:SpEL
1、Spring表达式语言(简称:SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。2、语法类似于EL:SpEL使用{...}作为定界符,所有在大括号内的字符都被认为是SpEL。3、SpEL为bean的属性进行动态赋值提供了便利。4、通过SpEL可以实现:\通过bean的id对bean进行引用\调用方法以及引用对象
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
5个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这