zoukankan      html  css  js  c++  java
  • Spring温故而知新 – bean的装配

    Spring装配机制

    Spring提供了三种主要的装配机制:

      1:通过XML进行显示配置

      2:通过Java代码显示配置

      3:自动化装配

    自动化装配

    Spring中IOC容器分两个步骤来完成自动化装配:

      组件扫描:Spring会自动发现应用上下文中所创建的 bean(通过定义资源的方式,让 Spring IoC 容器扫描对应的包,从而把 bean 装配进来)

      自动装配:spring自动满足满足bean之间的依赖(通过注解定义,使得一些依赖关系可以通过注解完成。)

    1 使用@Compoent注解申明bean

      这两天看出,冒出最多的一个词语“装配” 什么叫装配?谁能装配谁?引用书上的解释:创建应用对象之间写作关系的行为通常称为装配,这也是依赖注入的本质。定义解释了第一个疑问,那么谁装配谁?显然是spring容器装配bean。

      使用@Compoent注解,表明该类作为组件类,需要Spring IOC容器为这个类创建bean。

    package com.sl.ioc;
    import org.springframework.stereotype.Component;
    
    @Component
    public class Dog 
    {
       private Breed breed;
       public Breed getBreed() {
          return breed;
       }
    
       public void setBreed(Breed breed) {
          this.breed = breed;
       }
    }

    仅通过@Component注解Spring容器并不会主动创建bean,因为Spring的组件扫描默认是不启用的,就是说Spring根本还不认识这个类,所以我们需要启用Spring组件扫描,方式有两种:

       A: 使用@ComponentSacn注解发现bean

    package com.sl.ioc;
    
    import org.springframework.context.annotation.ComponentScan;
    
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan  //启用组件扫描
    public class AnimalConfig {
    
    }

    其实这个类并没有什么内容,默认情况下@ComponentScan会告知Spring扫描AnimalConfig所在的jar包下所有含有@Component修饰的类,并且通过IOC容器创建bean,到这里,可以创建一个测试类看一下结果了

    package com.sl.ioc;
    
    import static org.junit.Assert.assertNotNull;
    
    import org.junit.Test;
    
    import org.springframework.context.ApplicationContext;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class TestClass {
    
       @Test
       public void TestGetDoInstance() {
          //应用上下文
          ApplicationContext context = new AnnotationConfigApplicationContext(AnimalConfig.class);
    
          Dog dog = (Dog) context.getBean("dog");
    
          assertNotNull(dog);
       }
    }

    运行代发可以发现对象dog已经实例化了。

    上面的代码context.getBean("dog")可以发现,从应用上下文中获取bean时传的ID是”dog”,这是因为@Component注解默认将类名的首字母小写后作为bean的ID,当然也支持显示为bean设置ID,比如上面的代码想设置Bean标识为二哈,

    这样既可@Component("huskyDog")  使用传入beanname: context.getBean("huskyDog");

    同样关于@ ComponentScan  默认扫描被修饰类所在的包,如果需要扫描其他包也可以,只需要通过value属性传入包名即可@ComponentScan("com.sl.ioc")

    Value其实允许传入一个String[]数组,那么扫描多个包@ComponentScan(value= {"com.sl.ioc","com.sl.aop"}),验证代码这里略过

    启用组件扫描还有另外一种方式:使用XML配置

    <context:component-scan base-package="com.sl.ioc"></context:component-scan>

    2 使用@Autowried注解自动装配bean 

         通过前面的内容,已经可以让Spring自动发现bean并装载到应用上下文中,那么自动装配就是在这个基础上,将bean自动注入到依赖他的地方。@Autowired注解由Spring提供,可以对成员变量、方法以及构造函数进行注释

    package com.sl.ioc;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component; 
    
    @Component("animalD")
    public class Animal {
    
       @Autowired
       private Dog dog;  
    
        public void AnimalAction() {
    
           dog.Say();
    
        }
    }
    package com.sl.ioc;
    import org.springframework.stereotype.Component;
    
    @Component("huskyDog")
    public class Dog //extends Animal
    {
       private Breed breed;
    
       private String name;
    
       private Color color;
    
       public Breed getBreed() {
          return breed;
       }
    
       public void setBreed(Breed breed) {
          this.breed = breed;
       }
    
       public String getName() {
          return name;
       }
    
       public void setName(String name) {
          this.name = name;
       } 
    
       public Color getColor() {
          return color;
       }
    
       public void setColor(Color color) {
          this.color = color;
       }
    
       public void Say() {
         System.out.println("dog");
       } 
    
    }
    package com.sl.ioc;
    import static org.junit.Assert.assertNotNull;
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import com.yi.aop.User;
    
    //@RunWith(SpringJUnit4ClassRunner.class)
    //@ContextConfiguration(classes=AnimalConfig.class)
    public class TestClass { 
       @Test
       public void TestGetDoInstance() {   
          //应用上下文
          ApplicationContext context = new AnnotationConfigApplicationContext(AnimalConfig.class);
    
          Animal animal = (Animal) context.getBean("animalD");
    
          animal.AnimalAction();
       }
    }

    当然用在构造函数或者属性Setter方法上也可以:如下

    通过构造函数注入

    package com.sl.ioc;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component; 
    
    @Component("animalD")
    public class Animal {
    
       private Dog dog;
    
       @Autowired
       public void Animal(Dog dog) {
           this.dog = dog;
        }  
    
        public void AnimalAction()
        {
           dog.Say();
        }
    }

    通过Setter方法注入

    package com.sl.ioc;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    @Component(
    "animalD") public class Animal { private Dog dog; public void Animal() { } public Dog getDog() { return dog; } @Autowired public void setDog(Dog dog) { this.dog = dog; } public void AnimalAction() { dog.Say(); } }

    测试代码同上,略 。

    使用@Autowired注解后,Spring尝试从上下文中寻找对应的Bean,并将其注入到依赖它的位置,需要注意的是如果上下文中找不到对应的bean,则会抛异常,可以通过设置required=false来解决,但是使用bean对象的地方需要做null判断

    通过Java代码装配bean

    自动化装配自有它的优势,但是也有它缺陷

      1:代码中硬编码 

      2:无法解决使用第三方组件的问题

    所以必要时还是需要进行显示装配Java代码或者XML

    首先定义一个Config类,并且添加@Configuration注解, 标志这是一个配置类; 其中@Bean注解标识这个方法返回的bean对象并且需要装载到Spring应用的上下文中,默认情况下这个bean对象的name为该方法名DogInstance, @Bean注解支持为

    Bean对象起别名,通过name属性设置即可

    package com.sl.ioc;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AnimalConfig { 
    @Bean(
    "dog") public Dog DogInstance() { return new Dog(); } @Bean("animal") public Animal GetAnimal(Dog dog) { return new Animal(dog); } }

    测试代码:

    package com.sl.ioc;
    import static org.junit.Assert.assertNotNull;
    import static org.junit.Assert.assertSame;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import com.yi.aop.User;
    public class TestClass {
    
       @Test
       public void TestGetDoInstance() {
          //应用上下文
          ApplicationContext context = new AnnotationConfigApplicationContext(AnimalConfig.class);
          Dog dog = (Dog)context.getBean("dog");
          dog.Say();
          Animal animal = (Animal) context.getBean("animal");
          animal.AnimalAction();
          assertSame(dog, animal.getDog());
       }
    
    }
     

    解释一下:GetAnimal(Dog dog)本身依赖于Dog,Spring在调用次方法创建Animal 对象时会自动从上下文中寻找Dog对应的bean对象并注入到Animal构造函数中

     

    通过XML装配Bean

    使用XML装配bean需要在工程下创建一个标准的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: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" >
    
        <bean id="cat"  class="com.sl.ioc.Cat" ></bean>  
    
    </beans>

    通过属性注入初始化bean

    具体配置文件如下

    <?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" >  
        <!-- 申明一个bean -->
        <bean id="cat"  class="com.sl.ioc.Cat" >
           <property name="name" value="testCat"></property>
           <property name="color" value="YELLOW"></property>
           <property name="strs">
             <list>
             <value>str1</value>
             <value>str2</value>
           </list>
           </property>
        </bean> 
    </beans>

    使用<property>元素进行属性注入,其中name为对象属性名,value为需要注入的值,通过在<property>元素中内<list>元素进行集合的注入

    package com.sl.ioc;
    import java.util.List;
    public class Cat { 
    
       private String name;
       private Color color;
       private List<String> strs;
       public List<String> getStrs() {
          return strs;
    
       }
       public void setStrs(List<String> strs) {
          this.strs = strs;
       }
    
       public String getName() {
          return name;
       }
    
       public void setName(String name) {
          this.name = name;
       }
    
       public Color getColor() {
          return color;
       }
    
       public void setColor(Color color) {
          this.color = color;
       }
    }

    测试代码:

       @Test
       public void TestGetDoInstance() {    
          //应用上下文
          ApplicationContext context = new ClassPathXmlApplicationContext("xmlbean.xml");
          Cat cat = (Cat)context.getBean("cat");
          //cat.setName("Persian");
          System.out.println(cat.getName());
          System.out.println(cat.getColor());
          for(String s:cat.getStrs())
          {
             System.out.println(s);
          }
       }

    通过构造函数注入初始化bean

    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: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" >   
        <bean id="cat"  class="com.sl.ioc.Cat" >
          <constructor-arg name="name" value="testCat"></constructor-arg>
          <constructor-arg name="color" value="YELLOW"></constructor-arg>
        </bean> 
    
        <bean id="cat2"  class="com.sl.ioc.Cat" >
          <constructor-arg name="strs">
            <list>
              <value>str1</value>
              <value>str2</value>
            </list>
          </constructor-arg>
        </bean>   
    </beans>

    用<constructor-arg>元素进行构造函数参数注入<constructor-arg name="xxx" value="xxx"></constructor-arg>

    name:对应构造函数参数名,value:需要注入的值

    list:对应参数类型是集合,具体值通过多个value属性来设置

    其他<set> <map>等类型略

     

    package com.sl.ioc;
    import java.util.List;
    public class Cat {
    //通过构造函数注入 public Cat(String name,Color color){ this.name = name; this.color = color; } //通过构造函数注入List public Cat(List<String> strs){ this.strs = strs; } private String name; private Color color; private List<String> strs;
    public List<String> getStrs() { return strs; } public void setStrs(List<String> strs) { this.strs = strs; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } }

    测试代码:

      @Test
      public void TestGetDoInstance() {    
          //应用上下文
          ApplicationContext context = new ClassPathXmlApplicationContext("xmlbean.xml");
          Cat cat = (Cat)context.getBean("cat");
        
          System.out.println(cat.getName());
          System.out.println(cat.getColor());     
    
          Cat cat2 = (Cat)context.getBean("cat2");
          for(String s:cat2.getStrs())
          {
             System.out.println(s);
          }
       }
  • 相关阅读:
    ASP.NET MVC 实现二级域名(泛域名)
    linq to sql 语句基本查询(3):Select和Count/Sum/Min/Max/Avg
    DataSet用法详细
    MVC中返回Json的几种声明方式
    利用索引提高SQL Server数据处理的效率
    嫁给以下十种男人的女人离“地狱”就不远了
    Thinkpad x200 X201拆机换风扇教程 实图
    笔记一则
    冬季谨防胃病复发 放松精神吃温热食物
    就是这样给X200加内存的(申精)
  • 原文地址:https://www.cnblogs.com/ashleyboy/p/8988524.html
Copyright © 2011-2022 走看看