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、使用注解前的准备:
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.使用注解(类内部注解)
-
@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; }
-
@Qualifier注解(
当ioc容器根据属性类型去容器中找找到多个相同类型的组件,再将属性的名称作为组件(bean)的id去容器中查找找不到时就是用这两个注解搭配,指定需要装配的bean的id。
和Autowired搭配使用
-
@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>
- basePackage属性中可以包含多个包名,多个包含之间使用逗号或分号隔开。
- MapperScannerConfigurer会为所有又它创建的映射器实现开启自动装配,也就是MapperScannerConfigurer创建的所有映射器实现都会被自动注入SqlSessionFactory例,因此在如上示例中配置DAO组件时无需显示注入SqlSessionFactory实例
- 映射器被注册到Spring容器时,Spring会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名。例如EmpMapper类型的组件会被默认命名为empMapper