【第一章】常用注解【重点】
前提:必须要开始spring注解扫描<context:component-scan base-package=“com.itheima”/>
1 创建bean对象的基础注解【重要】
1.1 @Component、@Controller、@Service、@Repository的作用【重要】
Component [kəmˈpəʊnənt]n. 组成部分;成分;组件,元件
Repository [rɪˈpɒzətri]n. 贮藏室,仓库;知识库;智囊团
作用:相当于<bean id="" class="">,用于创建bean对象添加到Spring容器中
说明:这三个注解的作用是一样的,使用在类上面,都表示将自己定义的类交给Spring创建对象,保持到Spring容器中。只不过spring推荐我们在web层使用 @Controller注解,在service层使用@Service注解,在dao层使用@Repository注解。如果bean不在三层结构中,那么就是@Component。例如:
@Service("studentService") //参数为bean的名称
public class StudentServiceImpl implements StudentService {
//...
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
//...
}
1.2 @Scope注解的作用【了解】
作用:定义bean是单例还是多例
@Service("studentService") //参数为bean的名称
@Scope("singleton") //默认就是单例的,prototype表示多例
public class StudentServiceImpl implements StudentService {
//...
}
1.3 定义生命周期方法的注解【了解】
注意:如果jdk的版本高于1.8就需要额外导入一个依赖
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.29</version>
</dependency>
@PostConstruct、@PreDestroy用在方法上面,@PostConstruct定义初始化方法,@PreDestroy定义销毁的方法。
2 依赖注入注解【重要】
重点掌握@AutoWired注解,次掌握@qualifier和@Value注解,
作用:相当于<property name="" ref="" />用于给bean的属性注入数据。
==**@Autowired : **==自动按照类型注入,如果spring容器中同类型的对象有多个,那么按照参数名匹配id值,如果匹配不上就报错。推荐使用@Qualifier指定要匹配的bean的id值
@Qualifier("") : 用来指定匹配的bean的id值,@Qualifier可以用在成员变量上(必须要和@Autowired一起使用,不能单独使用),但是可以单独用在方法参数上。
==@Value(""):==用来注入普通类型,保持String类型,参数可以使用EL表达式
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Value("com.mysql.jdbc.Driver")
private String driverClassName;
}
3 纯注解开发【理解】
【第一步】使用配置类代替配置文件
**@Configuration :**用在类上,表示该类是一个spring配置类,代替applicationContext.xml配置文件
**@ComponentScan(""):**配置spring包扫描,相当于<context:component-scan base-package=“com.itheima”/>
**@PropertySource(""):**引入properties属性文件,相当于<context:property-placeholder location=“classpath:jdbc.properties”/>
@Configuration //用在类上,表示该类是一个spring配置类,代替applicationContext.xml配置文件
@ComponentScan("com.itheima")//相当于<context:component-scan base-package="com.itheima"/>开启spring注解扫描
@PropertySource("classpath:jdbc.properties")//<context:property-placeholder location="classpath:jdbc.properties"/>引入属性文件
public class SpringConfiguration {
}
【第二步】定义方法将第三方类交给spring管理
@Bean注解的作用:将方法的返回值存到spring容器中,可以指定名称,如果没有指定,默认名称就是方法名,方法名首字母小写。
@Configuration //用在类上,表示该类是一个spring配置类,代替applicationContext.xml配置文件
@ComponentScan("com.itheima")//相当于<context:component-scan base-package="com.itheima"/>开启spring注解扫描
@PropertySource("classpath:jdbc.properties")//<context:property-placeholder location="classpath:jdbc.properties"/>引入属性文件
public class SpringConfiguration {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/*
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
使用注解配置第三方类
*/
@Bean("dataSource") //也可以不指定名称,默认名称是方法名首字母小写
public DataSource getDataSource(){
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName(driverClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
【第三步】可选操作,引入分配置类
**@Import({JdbcConfig.class}):**表示引入一个名字叫做JdbcConfig的配置类
@Configuration //用在类上,表示该类是一个spring配置类,代替applicationContext.xml配置文件
@ComponentScan("com.itheima")//相当于<context:component-scan base-package="com.itheima"/>开启spring注解扫描
@PropertySource("classpath:jdbc.properties")//<context:property-placeholder location="classpath:jdbc.properties"/>引入属性文件
@Import({JdbcConfig.class})//<!--<import resource="classpath:xxxxx.xml"/>-->
public class SpringConfiguration {
}
上午内容回顾
1 创建Bean对象存到Spring容器中的注解【掌握】
@Controller、@Service、@Repository、@Component、@Bean
使用说明:
@Controller、@Service、@Repository(较少使用)、@Component用在类上的,给自定义类配置,可以用参数指定bean的名称
@Bean(较少使用)在配置类中用在方法上,给第三方类配置,将方法的返回值对象存的Spring容器中
2 依赖注入的注解【掌握】
注入引用类型:
@Autowired:表示按照类型自动注入对象,如果有多个同类型对象,则默认按照变量名和id值匹配。
@Qualifier("bean的名称"):集合@Autowired在变量上一起使用,指定使用哪个名称的对象。
注入普通类型:(包括String字符串)
@Value(""):支持EL表达式
3 其他注解【了解】,针对纯注解方式,在配置类中使用。
@Configuration :表示这个类是一个配置类
@ComponentScan(""):配置包扫描
@PropertySource(""):引入属性文件
@Import(""):引入分配置类
【第二章】bean加载控制【了解】
3.1)依赖加载
(1)@DependsOn
-
名称:@DependsOn
-
类型:类注解、方法注解
-
位置:bean定义的位置(类上或方法上)
-
作用:控制bean的加载顺序,使其在指定bean加载完毕后再加载
-
范例:
@DependsOn("beanId") public class ClassName { }
-
说明:
-
配置在方法上,使@DependsOn指定的bean优先于@Bean配置的bean进行加载
-
配置在类上,使@DependsOn指定的bean优先于当前类中所有@Bean配置的bean进行加载
-
配置在类上,使@DependsOn指定的bean优先于@Component等配置的bean进行加载
-
-
相关属性
- value(默认):设置当前bean所依赖的bean的id
(2)@Order
-
名称:@Order
-
类型:配置类注解
-
位置:配置类定义的位置(类上)
-
作用:控制配置类的加载顺序
-
范例:
@Order(1) public class SpringConfigClassName { }
(3)@Lazy
-
名称:@Lazy
-
类型:类注解、方法注解
-
位置:bean定义的位置(类上或方法上)
-
作用:控制bean的加载时机,使其延迟加载
-
范例:
@Lazy public class ClassName { }
3.2)依赖加载应用场景
@DependsOn
-
微信订阅号,发布消息和订阅消息的bean的加载顺序控制
-
双11活动期间,零点前是结算策略A,零点后是结算策略B,策略B操作的数据为促销数据。策略B加载顺序与促销数据的加载顺序
@Lazy
- 程序灾难出现后对应的应急预案处理是启动容器时加载时机
@Order
- 多个种类的配置出现后,优先加载系统级的,然后加载业务级的,避免细粒度的加载控制
【第三章】注解整合mybatis和junit案例【重点】
1 主配置类
@Configuration //表示该类是一个配置类
@ComponentScan("com.itheima")//<context:component-scan base-package="com.itheima.service"/>
@PropertySource("classpath:jdbc.properties")//<context:property-placeholder location="classpath:jdbc.properties"/>
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfiguration {
}
2 分配置类
- JdbcConfig配置类
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/*
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
*/
@Bean("dataSource") //方法的返回值对象在Spring容器
public DataSource getDataSource(){
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName(driverClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
- MybatisConfig配置类
public class MybatisConfig {
/*
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--必须有-->
<property name="dataSource" ref="dataSource"/>
<!--配置别名-->
<property name="typeAliasesPackage" value="com.itheima.bean"/>
<!--配置mybatis的核心配置文件的位置,核心配置文件中也可以设置别名、映射文件位置等操作-->
<!--<property name="configLocation" value="classpath:MybatisConfig.xml"/>-->
<!--如果映射文件和mapper接口在同一个包下-->
<!--<property name="mapperLocations" value="classpath:StudentMapper.xml"/>-->
</bean>
*/
@Bean //这个方法是由Spring容器调用,如果方法有参数,那么Spring会在容器中找对应的值/对象,参数按照类型匹配,相当于省略了@Autowired
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean ssfb=new SqlSessionFactoryBean();
ssfb.setDataSource(dataSource);
ssfb.setTypeAliasesPackage("com.itheima.bean");
return ssfb;
}
/*
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描mapper所在的包,映射文件需要和包在一起,如果不在一起,就需要在SqlSessionFactoryBean中配置额外指定-->
<property name="basePackage" value="com.itheima.mapper"/>
</bean>
*/
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
MapperScannerConfigurer msc=new MapperScannerConfigurer();
msc.setBasePackage("com.itheima.mapper");
return msc;
}
}
3 StudentServiceImpl注解配置
/*
<!--配置service-->
<bean id="studentService" class="com.itheima.service.impl.StudentServiceImpl">
<property name="mapper" ref="studentMapper"/>
</bean>
*/
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper mapper; //注入的是mapper的代理对象
//...
}
4 实现类代码测试
@Test
public void test1() throws IOException {
//创建Spring容器对象
//ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext ac=new AnnotationConfigApplicationContext(SpringConfiguration.class);
//获取service对象
StudentService studentService = ac.getBean("studentService", StudentService.class);
//执行操作,调用service的方法
List<Student> list = studentService.selectAll();
list.forEach(stu-> System.out.println(stu));
}
5 Spring整合junit单元测试
注意:junit的依赖至少要是4.12版本,可以是4.13等版本,否则出现如下异常:
【第一步】导入整合的依赖坐标spring-test
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
【第二步】使用spring提供的类加载器替换单元测试原有的类加载器
【第三步】告诉单元测试spring的配置文件或者配置类
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "classpath:applicationContext.xml") //加载配置文件
@ContextConfiguration(classes = {SpringConfiguration.class}) //加载配置类
public class StudentTest {
@Autowired //自动按照类型注入对象
private StudentService studentService;
//....
}
【第四章】IOC底层原理【了解】
5.1)IoC核心接口
5.2)组件扫描器
- 开发过程中,需要根据需求加载必要的bean,排除指定bean
5.3)设定组件扫描加载过滤器
-
名称:@ComponentScan
-
类型:类注解
-
位置:类定义上方
-
作用:设置spring配置加载类扫描规则
-
范例:
@ComponentScan( value="com.itheima", //设置基础扫描路径 excludeFilters = //设置过滤规则,当前为排除过滤 @ComponentScan.Filter( //设置过滤器 type= FilterType.ANNOTATION, //设置过滤方式为按照注解进行过滤 classes=Repository.class) //设置具体的过滤项,过滤所有@Repository修饰的bean )
includeFilters:设置包含性过滤器
excludeFilters:设置排除性过滤器
type:设置过滤器类型
5.4)自定义组件过滤器
-
名称:TypeFilter
-
类型:接口
-
作用:自定义类型过滤器
-
范例:
public class MyTypeFilter implements TypeFilter { public boolean match(MetadataReader mr, MetadataReaderFactory mrf) throws IOException { ClassMetadata cm = metadataReader.getClassMetadata(); tring className = cm.getClassName(); if(className.equals("com.itheima.dao.impl.BookDaoImpl")){ return false; } return false; } }
5.5)自定义导入器
-
bean只有通过配置才可以进入spring容器,被spring加载并控制
-
配置bean的方式如下:
-
XML文件中使用标签配置
-
使用@Component及衍生注解配置
-
-
企业开发过程中,通常需要配置大量的bean,需要一种快速高效配置大量bean的方式
ImportSelector
-
名称: ImportSelector
-
类型:接口
-
作用:自定义bean导入器
-
范例:
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata icm) { return new String[]{"com.itheima.dao.impl.AccountDaoImpl"}; } }
@Configuration @ComponentScan("com.itheima") @Import(MyImportSelector.class) public class SpringConfig { }
5.6)自定义注册器
-
名称:ImportBeanDefinitionRegistrar
-
类型:接口
-
作用:自定义bean定义注册器
-
范例:
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata icm, BeanDefinitionRegistry r) { ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(r, false); TypeFilter tf = new TypeFilter() { public boolean match(MetadataReader mr, MetadataReaderFactory mrf) throws IOException { return true; } }; scanner.addIncludeFilter(tf); //scanner.addExcludeFilter(tf); scanner.scan("com.itheima"); } }
5.7)bean初始化过程解析
5.8)bean初始化过程解析
-
BeanFactoryPostProcessor
-
作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理
-
运行时机:当前操作用于对工厂进行处理,仅运行一次
-
-
BeanPostProcessor
-
作用:定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理
-
运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作
-
-
InitializingBean
-
作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理
-
运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理
-
-
注意:上述操作均需要被spring容器加载放可运行
5.9)bean初始化过程解析
5.10)繁琐的bean初始化过程处理
- FactoryBean
- 对单一的bean的初始化过程进行封装,达到简化配置的目的
FactoryBean与BeanFactory区别
-
FactoryBean:封装单个bean的创建过程
-
BeanFactory:Spring容器顶层接口,定义了bean相关的获取操作