zoukankan      html  css  js  c++  java
  • 二、Spring装配Bean

    内容

    • 声明bean
    • 构造器注入和Setter方法注入
    • 装配Bean
    • 控制bean的创建和销毁

    关键词

    • 装配(wiring)
    • 组件扫描(component scanning)
    • 自动装配(AutoWiring)

    2.1 Spring配置的可选方案

    Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,而我们就是需要控制Spring要创建哪些Bean并且如何将其装配在一起。

    Spring提供了三种装配机制:

    1. 在XML中显式配置
    2. 在Java中进行显式配置(JavaConfig)
    3. 隐式的bean发现机制和自动装配

    web开发,提供三个@Component注解衍生注解(功能一样)取代
    @Repository: Dao层
    @Service: Service层
    @Controller:web层

    依赖注入:(给私有字段,或者setter方法)

    • 普通值:@Value("")
    • 引用值:
        1. 按照类型注入:@Autowired
        1. 按照名称注入
          1. @Autowired+@Qualifier("名称")
          1. @Resource("名称")

    2.2 自动化装配bean

    自动化装配实现

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

    组件扫描和自动装配在一起会显示出强大的威力,并将显式配置降低到最少。

    // java接口
    package Book;
    
    public interface PutBook {
    	void put();
    }
    
    // Java接口实现类
    package Book;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SetBook implements PutBook {
    	private String book_name = "Harry Potter";
    	private String author = "JK";
    	public void put() {
    		System.out.println("book_name"+book_name+"author:"+author);
    	}
    }
    

    注意第二段代码使用了@Component,这个注解将该类作为了组件类,并告知Spring为该类创建一个bean。但是该组件扫描默认不启用,需要显式配置Spring,从而命令它去寻找带有@Component的注解的类,并为其创建bean。

    // 启用组件扫描类
    package Book;
    
    import org.springframework.context.annotation.componentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class bookConfig {
    
    }
    

    ComponentScan默认会扫描鱼配置类相同的包,从而发现带有Component注解的类,并在Spring中自动为其创建一个bean

    // 测试代码
    package com.baidu.hankanvideo.book;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.ContextConfiguration;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = BookConfig.class)
    public class BookTest {
    
        @Autowired
        private PutBook putBook;
    
        @Test
        public void bookIsNotBeNull() {
            assertNotNull(putBook);
        }
    }
    

    以上为单元测试代码,通过检查PutBook属性是否为null,不为null则证明可以发现并注入。

    2.2.1 为组件扫描的bean命名

    Spring应用上下文中所有的bean都会给定一个ID。如果不指定则会根据类名来指定一个ID。

    @Component("lonelyHearts")
    public class SetBook implements PutBook {
    
    }
    
    

    2.2.2 设置组件扫描的基础包

    目前ComponentScan扫描包的范围会以配置类所在的包作为基础包(base package)进行扫描,所以指定包和多个包的配置如下。

    // 一、单个包
    @Configuration
    @ComponentScan("model")
    或者
    @ComponentScan(basePackages="model")
    
    // 二、多个包
    @Configuration
    @ComponentScan(basePackages={"model","service"})
    
    // 以上方法简单但是不够安全,如果包重构或者类被放到其他包,就会出现问题。所以指定类或者接口
    @Configuration
    @ComponentScan(basePackageClasses={Book.class,PutBook.class})
    
    

    2.2.3 通过为bean添加注解实现自动装配

    自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中描绘在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行的自动装配,在Spring中使用@AutoWired。

    // Java接口实现类
    package Book;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SetBook implements PutBook {
    	private String book_name = "Harry Potter";
    	private String author = "JK";
    
    	@AutoWired
    	public BookStore(PutBook putBook) {
    		this.book = putBook;
    	}
    
    	public void put() {
    		System.out.println("book_name"+book_name+"author:"+author);
    	}
    }
    

    总结:

    • @AutoWired可以用在构造器上
    • @AutoWired可以用在属性的Setter方法上
    • 还可以用在类的任何方法上

    2.3 通过Java代码装配bean(显式装配)

    将第三方库中的组件装配到应用中,就需要使用显式配置的方式,而上面通过组件扫描和自动装配的自动化配置是不可用的。

    JavaConfig是配置代码,意味着它不应该包含任何业务逻辑,JavaConfig也不应该侵入到业务逻辑代码中。因此常常会将JavaConfig放到单独的包中,使其与其他的应用程序逻辑分离开来。

    2.3.1 创建配置类

    // 启用组件扫描类
    package Book;
    
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class bookConfig {
    
    }
    

    单单只有@Configuration注解,但是缺少了上面的ComponentScan注解就会失效。
    那么显式配置怎么做呢?

    2.3.2 声明简单的bean

    // 启用组件扫描类
    package Book;
    
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class bookConfig {
    
    	// 新增一个方法注册一个Bean
    	@Bean
    	public CompactDisc sgtPeppers() {
    		return new SgtPeppers();
    	}
    
    }
    

    @Bean 注解会告诉Spring这个方法将返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含最终产生bean实例的逻辑。

    2.3.3 借助JavaConfig实现注入

    package soundsystem;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CDPlayerConfig {
      
      @Bean
      public CompactDisc compactDisc() {
        return new SgtPeppers();
      }
      
      @Bean
      public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
      }
    
    }
    
    

    cdPlayer()方法请求一个CompactDisc作为参数。当Spring调用cdPlayer()创建CDPlayerbean的时候,它会自动装配一个CompactDisc到配置方法中。然后方法体就可以按照合适的方式使用它。这种方法可以不需引用CompactDisc的@Bean的方法。

    2.4 总结

    Spring框架的核心是Spring容器,容器负责管理应用中组件的生命周期,它会创建这些组件并保证他们的依赖能够得到满足,保证组件完成预定的任务。

    写了一个小例子

    
    package com.example.springlearn.testDI;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Controller;
    
    
    // 表明这是一个Controller注解,等价与Component
    @Controller
    public class BookController {
    	// 自动注入并指定ID
        @Autowired
        @Qualifier("bsId")
        private BookService bookService;
    
        public void showBook() {
            bookService.saveBook();
        }
    }
    
    
    // 接口
    package com.example.springlearn.testDI;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Service;
    
    
    public interface BookService {
    
        public void saveBook();
    }
    
    
    // 接口的实现类
    package com.example.springlearn.testDI;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    @Service("bsId")
    public class BookServiceImpl implements BookService {
    
    //    以前
    //    private BookDao bookDao = new BookDaoImpl()
        private BookDao bookDao;
    	// 注入了Dao层
        @Autowired
        @Qualifier(value = "BookId")
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
    
        @Override
        public void saveBook() {
            this.bookDao.addBook();
        }
    }
    
    
    package com.example.springlearn.testDI;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Repository;
    
    // Dao层接口
    public interface BookDao {
    
        public void addBook();
    }
    
    package com.example.springlearn.testDI;
    
    import org.springframework.stereotype.Repository;
    
    // Dao层实现类,并用Repository注册
    @Repository("BookId")
    public class BookDaoImpl implements BookDao {
    
    
        @Override
        public void addBook() {
            System.out.println("add a book");
        }
    }
    
    
    
    // 写了一个测试类
    package com.example.springlearn;
    
    import com.example.springlearn.testDI.BookController;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class TestCarAspect {
    
        @Autowired
        private BookController bookController;
    
        @Test
        public void testCar() {
            bookController.showBook();
    
        }
    }
    
    谁不是孤身一人,翻山越岭
  • 相关阅读:
    Android
    nodejs 中 接受前端的数据请求的处理
    nodejs 文件操作
    nodejs 简单的搭建一个服务器
    angular 的跨域处理
    angular 的配置文件的应用
    angular 语法的应用
    淘宝的公共样式
    web编辑器的快捷键
    scss 用法 及 es6 用法讲解
  • 原文地址:https://www.cnblogs.com/hasz/p/12976813.html
Copyright © 2011-2022 走看看