Spring入门(三)----基于注解的IOC配置

三、基于注解的IOC配置


概念:基于注解的IOC配置和xml配置实现的功能都是一样的。

1、xml配置的形式

对上面的xml配置进行总结,可以分为以下四个功能

  • 用于创建对象
  • 用于注入数据
  • 用于改变作用范围
  • 和生命周期相关

2、基于注解配置

3.1用于创建对象的注解

  • @Component

作用:是将资源让Spring来管理,相当于xml中配置了一个bean。

属性:value:指定bean的id,如果不指定value属性,默认bean的id是当前的类名。首字母小写。

  • @Controller、@Service、@Reporsitory

它们三个注解都是针对一个的衍生注解,它们的作用及属性都是一模一样的。它们只不过是提供了更加明确的语义化。

@Controller :一般用于表现层的注解

@Service:一般用于业务层的注解

@Repository:一个用于持久层的注解

note:如果注解中有且仅有一个属性要赋值时,且名称是value,value的赋值是可以不写的

3.2用于注入数据的注解

它们的作用就和xml配置文件中的bean标签中写一个标签的作用是一样的

  • @AutoWired

自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。如果IOC容器没有任何bean的类型和注入的变量类型匹配,则报错。

它可以作用在变量上,也可以作用在方法上
在这里插入图片描述
先在Map的Value 结构中查找数据类型匹配的,如果匹配就直接注入数据。否则在Key中查找与变量名称匹配的。

  • @Qualifier

在自动按照类型注入的基础上,按照bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用,但是给方法参数注入时,可以独立使用。

属性: value:指定bean的id。

 @Autowired
 @Qualifier("accountDao1")//查找注解为"accountDao1"的对象注解
 private AccountDao accountDao;
  • @Resource

直接按照bean的Id注入,它也能注入其它bean类型

属性:name:指定bean的id

@Resource(name = "accountDao2")//查找注解为"accountDao2"的对象注解
private AccountDao accountDao;

Note:@AutoWire、@Qualifier、@Resource都只能注入其它bean类型,而基本的类型和String是无法使用这三个注解实现的,集合类型的注入只通过xml来实现

@Value

注入基本数据类型和String类型的数据

属性:value:用于指定值

3.3用于改变作用范围

@Scope

指定bean的作用范围,

属性:指定范围的值,取值为:Singleton 、prototype、request、session、globalsession

3.4和生命周期相关的

  • @PostConstruct:用于指定初始化方法
  • @PreDestory:用于指定销毁方法

3.5注解和xml的比较及选择

注解:配置简单,维护方便(我们找到了类,就相当于找到了对应的位置)

xml:修改时,不需要改动源码,不涉及重新编译和部署

基于XML的配置 基于注解的配置
Bean的定义 @Component 衍生类@Repository(持久层) @Service(业务层) @Controller(控制层)
Bean的名称 通过id或name指定 @Component(“person”)
Bean的注入 或者通过p命名空间 @Autowired(按名称注入) @Qualifier(按类型注入)
生命过程,Bean的作用范围 init-method 、destory-method;范围scope属性 @PostConstruct初始化 @PreDestory销毁 @Scope设置作用范围
适用场景 Bean来自第三方 Bean的实现类由用户自己开发

3、对注解配置进行改造

基于注解的springIOC配置中,bean对象的特点和基于xml配置是一模一样的。

Note:如果我们使用纯注解配置,我们依旧要使用bean.xml配置文件

bean.xml配置文件中依旧包含以下信息

 <context:component-scan base-package="com.simon"></context:component-scan>
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--配置数据库的必要信息-->
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&amp;serverTimezone=UTC"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
     </bean>

3.1使用配置类代替配置文件

  • @Configuration

作用:用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解,获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class)

属性:value:用于指定配置类的字节码

  • @ComponenScan

作用:用于指定要扫描的包。作用和在spring的xml配置文件中的:<context:component-scan base-package=“com.simon” />是一样的

属性:basePackage:用于指定要扫描的包,和该注解中的value属性作用是一样的

  • @Bean

作用:该注解只能写在方法上,表名此方法创建一个对象,并且存放入Spring容器中

属性:name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)

@Configuration
@ComponentScan("com.simon")
public class SpringConfiguration {

    @Bean(name = "queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        ComboPooledDataSource cbd = new ComboPooledDataSource();
        try {
            cbd.setDriverClass("com.mysql.cj.jdbc.Driver");
            cbd.setJdbcUrl("jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT");
            cbd.setUser("root");
            cbd.setPassword("root");
            return cbd;
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
}
}

3.2工程中的多个配置类

@Import

作用:用于导入其它配置类,在引入其它配置类时,其它配置类中的@Configuration写不写均可。

属性:value[]:用于指定其它的配置类字节码

  • 父配置类

    @Configuration
    @ComponentScan("com.simon")
    @Import(JdbcConfiguration.class)
    public class SpringConfiguration {
    
    }
    
  • 子配置类

    @Configuration
    public class JdbcConfiguration {
        @Bean(name = "queryRunner")
        public QueryRunner createQueryRunner(DataSource dataSource) {
            return new QueryRunner(dataSource);
        }
    
        @Bean(name = "dataSource")
        public DataSource createDataSource() {
            ComboPooledDataSource cbd = new ComboPooledDataSource();
            try {
                cbd.setDriverClass("com.mysql.cj.jdbc.Driver");
                cbd.setJdbcUrl("jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT");
                cbd.setUser("root");
                cbd.setPassword("root");
                return cbd;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

3.3注解@ProPertySource

用于加载.properties文件中的配置。如当我们配置数据源时,可以把连接数据库的信息写入到properties文件中

属性:value[]:用于指定properties文件位置,如果类路径下,需要加上classpath

@PropertySource("classpath:jdbcConfig.properties")//在父类上添加该注解即可
  • jdbcConfig.properties配置文件

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT
    jdbc.username=root
    jdbc.password=root
    
  • jdbcConfiguration类

    @Configuration
    public class JdbcConfiguration {
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        @Bean(name = "queryRunner")
        public QueryRunner createQueryRunner(DataSource dataSource) {
            return new QueryRunner(dataSource);
        }
    
        @Bean(name = "dataSource")
        public DataSource createDataSource() {
            ComboPooledDataSource cbd = new ComboPooledDataSource();
            try {
                cbd.setDriverClass(driver);
                cbd.setJdbcUrl(url);
                cbd.setUser(username);
                cbd.setPassword(password);
                return cbd;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

4、Spring整合Junit

  • 测试面临的问题,为什么要重新改造Junit
  • 应用程序的入口(main方法)
  • junit单元测试中,没有main方法也能执行,因为junit集成了一个main方法,该方法就会判断当前测试类中哪些方法有@Test注解,junit就让有Test注解方法执行
  • junit不会管我们是否采用Spring框架,因为在执行测试方法时,junit根本不知道我们是否使用了Spring框架,所以就不会为我们读取配置文件/配置类创建Spring核心容器
  • 整合的步骤
  • 导入spring整合的junit的jar(坐标),即spring-test

  • 使用Junit提供的一个注解把原有的main方法进行替换,替换成Spring提供的@Runwith

  • 告知spring的运行器、spring和ioc创建是基于xml还是注解的,并说明位置

@ContextConfiguration

locations:指定xml文件的位置,加上classpath关键字,表示在类路径下

@ContextConfiguration("classpath:bean.xml")

classes:指定注解类所在位置

@ContextConfiguration(classes = SpringConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {

   @Autowired
    private AccountService accountService;

    @Test
    public void testFindAll() {
        List<Account> list = accountService.findAllAccount();
        for (Account account : list) {
            System.out.println(account);
        }
    }
发布了77 篇原创文章 · 获赞 42 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/dreame_life/article/details/104495984
今日推荐