Spring IOC Bean装配 --day07

Spring IOC Bean装配 --day07

碰到的问题,以及思考解决不在这里写,本人日记:记录觉得需要记得常用描述,具体实现相关知识点。写日记是为了梳理知识点加深记忆。可能缺少很多信息,如果您看到给您道个歉

个人觉得总结的相当好的博文

一、概述

 IOC 控制反转:传统开发中,通过new来实现手动创建对象,IOC思想则是通过第三方来获取对象,不管对象怎么来的,你需要就跟他(Spring)说就行了,实现原理也是基于反射。

IOC 容器:
 Spring 提供 IoC 容器来管理和容纳我们所开发的各种各样的 Bean,并且我们可以从中获取各种发布在 Spring IoC 容器里的 Bean,并且通过描述可以得到它。
bean的理解,很好的一篇博文
Spring 容器设计
盗图:
ioc 接口
 1)BeanFactory: Spring IoC 容器所定义的最底层接口(getBean方法参数:Bean.class、“beanName”、“beanName”,Bean.class)。
 2)ApplicationContext:Spring IoC 容器所定义最高级接口之一,使用最广泛的接口,功能强大,支持方法较多。

二、简单实现

导入相关包(过)Maven管理
pojo类

public class Clothes {
    public Clothes()
    {
        System.out.println("一件衣服被创建了"+System.identityHashCode(this));
    }
    private     String color;

    private     int size;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }
    public void destory(){
        //System.identityHashCode(Object)方法可以返回对象的内存地址
        System.out.println("这件衣服被销毁了"+System.identityHashCode(this));
    }
}

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 class="my.test.Clothes" id="clothes" lazy-init="true"  destroy-method="destory" >
        <property name="color" value="red"/>
        <property name="size" value="33"/>
    </bean>
</beans>

测试类

        //初始化容器
        ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        //getBean方法拿到对象
        Clothes clothes1 = (Clothes)applicationContext.getBean("clothes");
        //打印结果信息
        System.out.println(clothes1.getColor()+clothes1.getSize());

结果


一件衣服被创建了1740846921
衣服颜色:red衣服尺码:33

三、Bean的装配

 根据优先级排序 顺序3→2→1,但由于种种因素的限制有些装配无法实现,只能采用次一级优先级方法来实现装配。

1.xml文件中显示配置(二中配置)

 简单易懂,当使用第三方类的时候,有些类并不是我们开发的,我们无法修改里面的代码只能使用xml进行配置。

<bean id="唯一标识,并不是必须 可以使用name代替 没有定义默认是全限定名#(0++)按定义次数递加" class="类的全限定名">
    <!--设值注入简单类型-->
    <property name="属性名" value="属性值" />
    <!--属性也是一个Bean 通过refy引用-->
    <property name="属性名" ref="另一个Bean的id或者name"/>
     <property name="属性名" >
        <ref bean="另一个Bean的id或者name"/>
     </property>
    <property name="属性名">
           <value>另一种值写入方式</value>
           <!--除了value 还可以 是Set、Map、List、Array、Properties 等-->
           <!--和各自子节点的对应关系
                list\Set\Array:value
                Map:entry
                Properties :property(必填key属性)     
           -->
    </property>

</bean>

命名空间装配
c-命名空间:用于构造注入简化写法:

<!--未引入命名空间-->
<bean....>
<constructor-arg name="id" value="1" />
<constructor-arg name="name" value="学生1"/>
</bean>
<!-- 引入c- 命名空间后-->
<bean name="student2" class="pojo.Student"
      c:id="2" c:name="学生2"/>
<!--如果需要设置引用的话在对应参数名后加上 (-ref) 比如:c:name-ref="beanId"
    也可以用下标代替属性名
    如:c:_0=""、c:_1=""

  -->

p-命名空间:简化设置注入写法,写法和c-命名空间简写规则一样c换成p

util-命名空间:简化集合类元素

<!-- 引入util-命名空间之前 -->
<property name="list">
   <list>
       <ref bean="bean1"/>
       <ref bean="bean2"/>
   </list>
</property>

<!-- 引入util-命名空间之后 -->
<util:list id="list">
   <ref bean="bean1"/>
   <ref bean="bean2"/>
</util:list>

元素 描述
<util:constant> 引用某个类型的 public static 域,并将其暴露为 bean
<util:list> 创建一个 java.util.List 类型的 bean,其中包含值或引用
<util:map> 创建一个 java.util.map 类型的 bean,其中包含值或引用
<util:properties> 创建一个 java.util.Properties 类型的 bean
<util:property-path> 引用一个 bean 的属性(或内嵌属性),并将其暴露为 bean
<util:set> 创建一个 java.util.Set 类型的 bean,其中包含值或引用

通常一个配置文件写大量Bean配置信息会变得十分臃肿,可以通过import引入其他配置文件
写法:

<import resource="bean.xml" />

2.java类和接口中配置

 可以减少xml文件中复杂的手动配置,可以实现自动装配。
两种使IOC容器能发现Bean的方法:
 1)包扫描
  定义扫描的包资源,让Spring IOC去扫描相应的包,将对应Bean装配进来
 2)自动装配
  通过注解定义,使得一些依赖关系可以通过注解完成。

@Component、@Value、@ComponentScan
简单规则:

@Component(value=“Bean的id,如果不写默认类名”)
@value(“下面属性的注入值”)
@ComponentScan:扫描当前包路径下的所有被@Compoent注解标记的pojo类。

示例代码:

//测试pojo类
package my.test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value="clothes")
public class Clothes {
    public Clothes()
    {
        System.out.println("一件衣服被创建了"+System.identityHashCode(this));
    }
    @Value("red")
    private     String color;
    @Value("31")
    private     int size;
    //getter setter and others
}

//测试类
@ComponentScan
public class SpringTest {
    public static void main(String args[])
    {
        //初始化容器
        //ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Clothes.class);

        //getBean方法拿到对象
        Clothes clothes1 = (Clothes)applicationContext.getBean("clothes",Clothes.class);
        //打印结果信息
        System.out.println("衣服颜色:"+clothes1.getColor()+"衣服尺码:"+clothes1.getSize());

    }

}

实验成功

@Value(只能注入简单类型值,不能注入对象)、@ComponentScan(只能扫描当前包)

@ComponentScan配置项:
 basePackages:Spring 根据它配置的信息去扫描对应的包以及子包,装配配置好的Bean
 basePackageClasses:他会根据设定的类去自动查找到类所在的包,将配置好的Bean装配进来。

@ComponentScan(basePackages = "my.test")
@ComponentScan(basePackageClasses = my.test.Clothes.class)

注意:basePackages 和 basePackageClasses 选择
 basePackages较简单且易读,因为设置过程中使用字符串传递参数,写入错误不会提示,在大量重构的项目中,经常需要修改报名 不适合使用。basePackageClasses 中包名变化,原来写入信息和当前包名不符合,或类名不符 IDE中会报错

@Autowired
 通过它可以实现对象自动装配,用它标记一个自定义类型属性,等到Spring IOC 容器已经定位好所有Bean的时候,按照这个属性的自定义类型,去查找Bean,对这个属性实现装配

创建一个公司类型,让衣服类拥有一个公司属性,并用@Autowired
代码:

//公司

@Component(value="company")
public class Company {
      @Value("小公司")
      private  String companyName;

      public String getCompanyName() {
            return companyName;
      }

      public void setCompanyName(String companyName) {
            this.companyName = companyName;
      }
}
//衣服加入对公司所在包的扫描、或扫描公司类
    @Autowired
    private Company company;
    //getter、setter..

测试成功。

注意:
 @Autowired默认能找到相应的Bean注入,如果注入失败会报错。解决方法:设置@Autowired(required = false) 设置注入失败不会报错。
 注解不仅仅能配置在属性之上,还允许方法配置/
 当发现多个相同类型的Bean 无法确定注入哪一个Bean:@Primary 标记一个类,这个类满足条件会被优先注入,@Qualifier指定注入的Bean的id

3.隐式Bean发现自动装配

@Bean
 上面通过@Component来装配Bean,该注解使用在类上,引用第三方包的时候很不方便,&Bean可以用到到第三方包的方法上。
测试代码:

@Configuration//注解相当于 XML 文件的根元素,必须要,有了才能解析其中的 @Bean
public class BeanTest {
    @Bean(name = "testName")
    public String  test()
    {
        System.out.println("测试Bean方法");
        return "必须有返回值";
    }

}
//测试类
    // 在 pojo 包下扫描
        ApplicationContext context = new AnnotationConfigApplicationContext("my.test");
        context.getBean("testName");
        ((AnnotationConfigApplicationContext) context).close();
//测试成功

@Bean只用于方法,方法必须有返回值否则报错

Bean配置项

属性 作用
name: 是一个字符串数组,允许配置多个 BeanName
autowire: 标志是否是一个引用的 Bean 对象,默认值是 Autowire.NO
initMethod: 自定义初始化方法
destroyMethod: 自定义销毁方法

猜你喜欢

转载自blog.csdn.net/qq_38325853/article/details/85218913
今日推荐