美文网首页菜鸟学习Spring
控制反转IOC(DI依赖注入)

控制反转IOC(DI依赖注入)

作者: 我弟是个程序员 | 来源:发表于2017-07-14 15:42 被阅读0次

    Spring具有非常大的灵活性,它提供了三种主要的装配机制:

    • 在XML中进行显式配置。
    • 在Java中进行显式配置。
    • 隐式的bean发现机制和自动装配。
    一、自动化装配bean

    Spring从两个角度来实现自动化装配:

    • 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
    • 自动装配(autowiring):Spring自动满足bean之间的依赖。

    1.首先创建CompactDisc.java文件,里面顶一个一个接口:

    package com.df.test.service.impl;
    
    public interface CompactDisc {
        void play();
    }
    

    2.然后定义它的实现类:

    package com.df.test.service.impl;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class SgtPeppers implements CompactDisc {
    
        public void play() {
            // TODO Auto-generated method stub
            System.out.println("播放音乐...");
        }
    
    }
    

    需要注意的就是SgtPeppers类上使用了@Component注解。这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。没有必要显式配置SgtPeppersbean,因为这个类使用了@Component注解,所以Spring会为你把事情处理妥当。不过,组件扫描默认是不启用的。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。如下设置Spring对组件进行扫描:

    package com.df.test.service.impl;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class CDPlayerConfig {
    
    }
    

    使用了@ComponentScan注解,这个注解能够在Spring中启用组件扫描。如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于com.df.test.service.impl包中,因此Spring将会扫描这个包以及这个包下的所有子包,查找带有@Component注解的类。并且会在Spring中自动为其创建一个bean。
    当然也可以XML来启用组件扫描:

    <context:component-scan base-package="com.df.test.service.impl" />
    

    测试代码如下:

    package com.df.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.df.test.service.impl.CDPlayerConfig;
    import com.df.test.service.impl.CompactDisc;
    import com.df.test.service.impl.SgtPeppers;
    
    @RunWith(SpringJUnit4ClassRunner.class) //表示继承了SpringJUnit4ClassRunner类
    @ContextConfiguration(classes= CDPlayerConfig.class)
    public class JavaTestMethod {
        @Autowired CompactDisc cd;//这里,不论我是用CompactDisc接口还是SgtPeppers实现类,下面都有输出,都是同一个对象SgtPeppers。
        
        @Test
        public void testMethod() {
            cd.play();
        }
    }
    

    @Component基本使用。
    Spring应用上下文中所有的bean都会给定一个ID。在前面的例子中,尽管我们没有明确地为SgtPeppersbean设置ID,但Spring会根据类名为其指定一个ID。具体来讲,这个bean所给定的ID为sgtPeppers,也就是将类名的第一个字母变为小写。我们也可以给bean命名,像下面代码这样。有时候可以用@Named代替@Component使用:

    @Component("myComponentName")
    public class SgtPeppers implements CompactDisc {
              ...
    }
    

    @ComponentScan基本使用。
    不但可以默认设置,还可以指定多个不同的基础包作为扫描对象,使用basePackages属性,String[]类型
    另外一种方法,那就是将其指定为包中所包含的类或接口,使用 basePackageClasses属性,这些类所在的包将会作为组件扫描的基础包。,Class<?>[]类型:

    //一下两种方法,任意一种都可以实现
    
    @Configuration
    @ComponentScan(basePackages = {"com.df.test.service.impl","com.df.test.dao"})
    public class CDPlayerConfig {
    
    }
    
    @Configuration
    @ComponentScan(basePackageClasses = {SgtPeppers.class})
    public class CDPlayerConfig {
    
    }
    

    @Autowired 实现自动装配。
    简单来说,自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。因为是按照类型进行匹配,所以如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配。@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上,还可以在属性上。如下代码,下面三个属性对象,都会完成自动装配,可以用@Inject在大多数情况下来代替@Autowired 。@Named和@Inject来源于Java依赖注入规范。

    package com.df.test.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CDPlayer {
    
        @Autowired 
        private CompactDisc cd;
        
        private CompactDisc cd2;
        
        private CompactDisc cd3;
    
        @Autowired 
        public CDPlayer(CompactDisc cd2) {
            this.cd2 = cd2;
        }
        
        @Autowired 
        public void setCd3(CompactDisc cd3) {
            this.cd3 = cd3;
        }
        
        public void play(){
            cd.play();
            cd2.play();
            cd3.play();
        }   
    }
    

    二、通过Java代码装配bean

    通过JavaConfig显式配置Spring:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CDPlayer02 {
        
        @Bean
        public CompactDisc getBeanI(){
            return new SgtPeppers();
        }
    }
    

    @Bean注解基本使用。
    创建JavaConfig类的关键在于为其添加@Configuration注解,@Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。所以这里就很灵活了,可以一个方法,返回很多个不同的对象根据不同的逻辑条件。默认情况下,bean的ID与带有@Bean注解的方法名是一样的。也可以通过name属性指定一个不同的名字。

    三、通过XML装配bean

    Spring刚出来的时候,就是以这种方式。所以这里就不做过多解释了。可以通过set方法注入,也可以通过构造方法注入。

    <?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-2.5.xsd">
    
        <bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
    </beans>
    

    我是分割线


    混合配置

    以上已经将三种装配bean的 方式讲完了,现在说说混合配置
    1.JavaConfig配置之间相互引用
    假设由于有两个JavaConfig配置的类:

    @Configuration
    public class CDPlayer02 {
        @Bean
        public CompactDisc getBean02(){
            return new SgtPeppers02();
        }
    }
    
    @Configuration
    public class CDPlayer01 {
        @Bean
        public CompactDisc getBea01(){
            return new SgtPeppers01();
        }
    }
    

    我们需要有一种方式将这两个类组合在一起,可以这样做,使用@Import:

    @Configuration
    @Import(CDPlayer02 .class)
    public class CDPlayer01 {
        @Bean
        public CompactDisc getBea01(){
            return new SgtPeppers01();
        }
    }
    

    也可以干脆这样:

    @Configuration
    @Import({CDPlayer01 .class,CDPlayer2 .class})
    public class CDPlayer01 {
    }
    

    2.在JavaConfig中引用XML配置
    假设有cd-config.xml配置文件

    @Configuration
    @Import(CDPlayer02 .class)
    @ImportResource("classpath:cd-config.xml")
    public class CDPlayer01 {
        @Bean
        public CompactDisc getBea01(){
            return new SgtPeppers01();
        }
    }
    

    3.在XML配置中引用JavaConfig

    <?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-2.5.xsd">
         <!--  这就是那个JavaConfig配置类 -->
        <bean class = "com.df.test.service.impl.CDConfig"/> 
    
        <bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
    </beans>
    

    4.在XML配置中引用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-2.5.xsd">
         <!--  这就是那个JavaConfig配置类 -->
        <bean class = "com.df.test.service.impl.CDConfig"/> 
        <!--  这就是另一个那个xml配置文件 -->
        <improt resource = "cdplayer-config.xml" />
    
    </beans>
    

    以上就是bean装配的三种方式。上一篇Spring容器

    相关文章

      网友评论

        本文标题:控制反转IOC(DI依赖注入)

        本文链接:https://www.haomeiwen.com/subject/vdenhxtx.html