Spring框架配置进阶_自动装配(XML和注解)

Spring配置进阶

Spring 容器提供配置元数据有三种方式

  • XML配置文件。
  • 基于注解的配置。
  • 基于java的配置。

一、自动装配

应用程序上下文为你找出依赖项的过程,Spring会在上下文中自动查找,并自动给bean装配与其关联的属性

Spring中实现自动装配的方式有两种:

  • XML文件
  • 注解

(1)通过xml文件实现自动装配

1、通过xml文件实现自动装配

xml配置文件中的<bean>要配置autowire属性

autowire属性值:

模式 描述
no 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。,
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
1)byName属性值

Spring会根据class属性找到实体类,然后查询实体类中所有setter方法的名字,根据setter方法后面的名字,再到配置文件中寻找一个与该名字相同id的Bean,注入进来

autowire属性赋值>>class找到对应类>>查询对应setter方法>>对应id的Bean对象

xml 复制代码
<bean id="iDeptDao" class="org.example.dao.impl.DeptImpl" autowire="byName"/>
2)byType属性值

Spring会自动寻找一个与该属性类型相同的Bean,注入进来

xml 复制代码
<bean id="iDeptService" class="org.example.service.impl.DeptServiceImpl autowire="byType">

(2)通过注解实现自动装配

二、Spring注解分类

1、使用注解前的准备:

//spring-config.xml文件配置数据

xml 复制代码
<!--    加入扫描包,配置根路径,查找根路径下使用的注解-->
<context:component-scan base-package="org.example"/>

以注解为主,XML为辅。

@Component(组件),@Service(服务),@Controller(控制器),@Repository(*/rɪˈpɑːzətɔːri/*数据仓库)

1、Spring类注解

@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named注解,都是添加在类上面的类级别注解

Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中。

1、使用asm技术扫描.class文件,并将包含@Component、@Controller、@Service、@Repository或者其他自定义的的bean注册到beanFactory中,

  • @Component : 通配
  • @Repository:用于声明DAO层的
  • @Service:用于业务层
  • @Controller:用于控制器 (暂时先不用,后面接触Spring MVC再使用)

2、然后spring在注册处理器

3、实例化处理器,然后将其放到beanPostFactory中,然后我们就可以在类中进行使用了。

4、创建bean时,会自动调用相应的处理器进行处理。

2、类内部注解

@Autowire、@Value、@Resource注解等,都是添加在类内部的字段或者方法上的类内部注解。

SpringIoC容器通过Bean后置注解处理器解析Bean内部的注解,比如Spring实现@Autowire解析和注入的核心的类是通过AutowiredAnnotationBeanPostProcessor来实现的

java 复制代码
//@Component("deptService"),
//@Service类注解Service层
@Service("deptService")
public class DeptServiceImpl implements IDeptService {
    @Autowired//Autowired类内部注解,可以注解变量或方法
    private IDeptMapper deptMapper;
}

三、注解实现自动装配

2.使用注解(类内部注解)

  1. @Autowired注解

    只按照类型byType匹配, 默认情况匹配的Bean只有一个,匹配不到报错BeanCreationException 异常

    • 可使用在变量和setter方法上, xml文件中注解autowrie删除

    若要匹配多个类型, 引入:

    java 复制代码
    //1.注解在属性上
    @Autowired
    @Qualifier("类型2")
    private IDeptMapper deptMapper;
    //2.注解setter方法上(同一变量的2种二选一)
        @Autowired
        public void setiDeptDaoMapper(IDeptMapper iDeptMapper) {
            this.iDeptMapper = iDeptMapper;
        }
  2. @Qualifier注解(

    当ioc容器根据属性类型去容器中找找到多个相同类型的组件,再将属性的名称作为组件(bean)的id去容器中查找找不到时就是用这两个注解搭配,指定需要装配的bean的id。

    和Autowired搭配使用

  3. @Resource注解

    • 可以写在字段和setter方法上(2选1)

    默认按名称进行装配

    @Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型

    • 默认按名字匹配

      java 复制代码
      @Resource
      private SqlSessionFactory sqlSessionFactory;
    • 按类型: 效果和@Autowired一样

    java 复制代码
     @Resource(type = SqlSessionFactory.class)
        private SqlSessionFactory sqlSessionFactory;
    • 匹配顺序

      同时name和type一致的bean对象>>指定的name>>指定type>>什么也没指定name

3.基于注解声明组件(类注解)

目前常用的组件有:@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库)

1.@Component注解

通用的注解,可标注任意类为 Spring 组件(一个 Bean 不知道属于哪个层时使用)

说明:如果一个类中有@Component,没有指定名称,那么这个组件名称就是类名首字母小写

java 复制代码
//@Component //默认空指向deptMapperImpl
@Component("deptMapper")
public class DeptMapperImpl implements IDeptMapper {
    @Resource
    private SqlSessionFactory sqlSessionFactory;
}

4.使用完类注解

删除掉声明的dao层的bean信息,以及service信息,只保留基础配置信息

xml 复制代码
//bean标签都删除
<!--    <bean id="iDeptDao" class="org.example.dao.impl.DeptImpltowire="byName"> -->
<!--    <bean id="iDeptDao1" class="org.example.dao.impl.IDeptMapperImpl1 -->

四.JavaConfig

JavaConfig是指基于java配置的spring。传统的Spring一般都是基本xml配置的,后来spring3.0新增了许多JavaConfig的注解

任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类

java 复制代码
package org.example;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author Arran
 * @version 1.0
 * @description: 基于java配置的spring
 * @date 2024/07/06 上午 11:59
 */
//在类上打上这一标签,表示这个类是配置类
//表明该类是一个JavaConfig形式的Spring Ioc容器的配置类
 @Configuration//被该注解标识的类,
//读取数据源
@PropertySource("classpath:source.properties")
public class Myconfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    //相当于spring.xml文件的bean对象
    @Bean
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }
}
注解 说明
@Configuration 在类上打上这一标签,表示这个类是配置类
@ComponentScan 相当于xml的<context:componentscan basepakage=>
@Bean bean的定义,相当于xml的<bean id="objectMapper" class="org.it.map.ObjectMapper" />
@EnableWebMvc 相当于xml的<mvc:annotation-driven>,springMVC阶段涉及
@ImportResource 相当于xml的 <import resource="applicationContext-cache.xml">
@PropertySource spring 3.1开始引入,它是基于java config的注解,用于读取properties文件
@Profile spring3.1开始引入,一般用于多环境配置,激活时可用@ActiveProfiles注解,@ActiveProfiles("dev")
@Value 读取外部配置文件对应的property

xml和java配置的区别

1.表达形式层面(二者区别)
  • 基于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-3.0.xsd"> </beans>

  • 而基于JavaConfig的配置方式是这样:

    @Configuration

    public class MockConfiguration{

    //bean定义

    }

2.注册bean定义层面
  • 基于XML的配置形式是这样:

    <bean id="mockService" class="...MockServiceImpl">

    ...

    </bean>

  • 而基于JavaConfig的配置形式是这样的:

    @Configuration

    public class MockConfiguration{

    @Bean

    public MockService mockService(){

    return new MockServiceImpl();

    }

    }

    任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。

    @Bean一般用在使用第三方类来生成对象注入到spring容器的情况下使用

3.表达依赖注入关系层面
  • 为了表达bean与bean之间的依赖关系,在XML形式中一般是这样:

    <bean id="dependencyService" class="DependencyServiceImpl"></bean>

    <bean id="mockService" class="...MockServiceImpl">

    <propery name ="dependencyService" ref="dependencyService" />

    </bean>

  • 而基于JavaConfig的配置形式是这样的:

    @Configuration

    public class MockConfiguration{

    @Bean

    public DependencyService dependencyService(){

    return new DependencyServiceImpl();

    }

如果一个bean的定义依赖其他bean,则直接调用对应的JavaConfig类中依赖bean的创建方法就可以了。

五MapperScannerConfigurer配置

MyBatis中可以使用SqlSession的getMapper(Class type)方法,根据指定的映射器和映射文件直接生成实现类,这样不必自行编写映射器的实现类,就可以调用映射器的方法进行功能实现。

xml 复制代码
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    <property name="basePackage" value="mapper路径"></property>
</bean>
  1. basePackage属性中可以包含多个包名,多个包含之间使用逗号或分号隔开。
  2. MapperScannerConfigurer会为所有又它创建的映射器实现开启自动装配,也就是MapperScannerConfigurer创建的所有映射器实现都会被自动注入SqlSessionFactory例,因此在如上示例中配置DAO组件时无需显示注入SqlSessionFactory实例
  3. 映射器被注册到Spring容器时,Spring会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名。例如EmpMapper类型的组件会被默认命名为empMapper
相关推荐
面朝大海,春不暖,花不开15 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y15 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java
白宇横流学长1 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
fat house cat_2 小时前
【redis】线程IO模型
java·redis
stein_java3 小时前
springMVC-10验证及国际化
java·spring
weixin_478689763 小时前
C++ 对 C 的兼容性
java·c语言·c++