目录
1.在spring中对象无需自己查找或创建与其关联的其他对象.相反,容器负责把需要相互协作的对象引用赋予各个对象.
2.在spring中,由ioc容器管理着的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。
@Component和@Bean以及@Autowired,@MapperScan区别与联系
1.在spring中对象无需自己查找或创建与其关联的其他对象.相反,容器负责把需要相互协作的对象引用赋予各个对象.
创建对象之间的协作关系的行为通常称为装配,也就是依赖注入DI.
2.在spring中,由ioc容器管理着的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。
3.三种装配机制(可以随便搭配.尽量选择适合你的项目)
- 在xml中进行显示配置
- 在java中进行显示配置
- 隐式的bean发现机制和自动装配
建议:尽可能的使用自动配置的机.显式配置越少越好.当必须要显式配置使用类型安全并且比xml更强大的javaconfig.
4.自动化装配bean
在便利性方面最强大的还是spring的自动化配置
spring从 两个角度来实现自动化装配
- 组件扫描componentScan:spring会自动发现应用上下文所创建的bean
- 自动装配autoAwired:spring自动满足bean之间的依赖
组件扫描和自动装配组合在一起就能发挥强大的威力,他们能够将你的显示配置降低到最低.
注意:组件扫描默认是不启用的,我们需要显式的配置一下spring,从而命令他寻找带有@component注解的类.如果@componentScan没有其他配置的话,这个注解会默认扫描与配置相同的包及所有子包.如果是xml配置配置如下:<context:component-scan base-package=' '/>
@Component和@Bean以及@Autowired,@MapperScan区别与联系
在xml时代,一个xml配置文件里面有很多个bean, 每个bean都对应着一个class,可能是controller,可能是service,可能是dao,
进入@Configuration时代
@Configuration
注解就相当于xml配置文件,告诉Spring我这里有好多bean要交给你管理@Bean
注解就相当于xml配置文件里面的bean,告诉Spring这个被注解的类就交给你管理
@Component
@Controller
、@Service
、@Repository
都是@Component
的更具体一点的实现,注解在 类上,直接告诉spring,这个类你替我管理着吧.
那么为什么有@component注解还有@configuration和@bean注解呢?
举例说明,如果我们使用别的类(已经是打好的jar)没法修改了,那么我们使用@Configuration和@bean了.(注意使用@bean必须有@configuration)
@MapperScan此注解是springboot集成mybatis的注解.在SpringBoot中集成MyBatis,可以在mapper接口上添加@Mapper注解,将mapper注入到Spring,但是如果每一给mapper都添加@mapper注解会很麻烦,这时可以使用@MapperScan注解来扫描包。
经测试发现,@MapperScan注解只会扫描包中的接口,不会扫描类,所以可以在包中写Provider类。
@Repository 与 @Mapper的区别与联系
@Mapper 是 Mybatis 的注解,和 Spring 没有关系,@Repository(注解在实现类上,不是service) 是 Spring 的注解,用于声明一个 Bean。
5.为组件扫描的bean命名
spring应用上下文会自动为所有的bean给定一个ID,ID是类名第一个字母变成小写.如果需要指定id名称,如下做法@Component("自定义ID名称").也可以使用@Named("自定义ID名称"),只不过没人使用这个注解
6.设置组件扫描的基础包
@ComponentScan(basePackages=""),发现basePackages是复数,如猜测一样,可以设置多个基础包.以数组的形式即可
注意string类型表示值得的这种方法是不安全的,可以使用扫描指定类或接口
@COmponentScan(basePackageClassess="")指定包中所含的接口或类
7.通过为bean添加注解实现自动装配
@AutoWired注入的时候如果没有匹配的bean会抛出异常,可以将@autowired的required属性设置成false ,
注意如果设置成false后,spring也会执行自动装配,没有bean的话会让bean处于未装配状态.如果使用这个未装配的bean会出现空指针
@AutoWired==@Inject 如同@Component==@Named
8.通过java代码装配bean
想要将第三方库中的组件装配到你的应用中,此时自动装配是没有办法实现注解的,因此必须采用显式装配的方式
配置类代码与逻辑代码分离开,应该放到单独的包
其关键是添加@configuration注解,此注解表名这是一个配置类,
要在类中声明bean,我们需要编写一个方法,这个方法返回我们需要类型的实例,然后在这个方法上添加@bean注解.
@bean注解告诉spring这个方法将会返回一个对象.,该对象要注册为spring上下文bean.bean默认的ID是@bean注解的方法名,可以改变ID,如@bean(name='''');
注意如下:得到Compatdisc的bean不是每次调用setg()得到的,spring将会拦截添加@bean注解的所有调用.,并确保直接返回该方法所创建的bean.也就是说spring的bean时单例的.
带有@bean注解的方法只是采用构造器和setter来注入仅仅是因为受java语言的限制
public class a{
@Bean
public Compactdisc setg(){
return new CompactdiscImpl();
}
}
public class b{
@Bean
public CDPlay set1(){
return new CDPlay(setg())
}
@Bean
public CDPlay set2(){
return new CDPlay(setg())
}
}
9.通过xml装配bean
此xml配置只是用来帮助你维护已有xml配置,在完成新的spring工作时,还是使用自动配置和javaconfig,所以我不作记录
10.导入和混合配置
- 在javaconfig中引用xml的配置
如果一个配置类臃肿需要拆分,我们可以将它么拆分成多个配置类.
如果有两个@configuration配置类,我们需要将这个两个类组合在一起,可以在其中一个或者新建一个配置类中的类名上注解@import(xxx.class).
如果有一个@configuration类,还有一个xml形式的配置bean.需要将他们组合在一起,可以在@configuration类中类名上使用注解@importResource("classpath:xxx.xml") <!--注:@import和@imporSouce注解用于xml或javaconfig的bean没有被扫描或没有注入容器的情况下使用-->
- 在xml配置中引用javaConfig
在xml中引入xml文件使用<import resource="xxx.xml"/>
11.高级装配
环境与profile
- 配置profile bean
有几种方式配置profile:
在java配置中,可以使用@profile注解指定某个bean属于哪个一个profile,如在有bean的类名上注解@profile("dev")(spring3.0之前只能配置类名上,3.2之后也可以配置在方法上)
注意:只有指定的profile激活后,相应的bean才会被创建,其他没有被指定profile的bean都会被创建
在xml中配置profile,如<beans profile=" "></beans> - 激活bean
spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:active和default.如果有设置active会使用active,如果没有就使用default,.如果都没有设置,那么就只创建没有定义在profile中的bean
有多种方式来设置整两个属性
1)作为dispatchServlet的初始化参数
2)作为web应用的上下文参数
3)在集成测试上使用@ActiveProfile注解设置 ,如@ActiveProfile("dev") - 条件化创建bean
spring4引入一个新的@Conditional注解,他可以用到带有@bean注解的方法上,如果给定的条件计算结果为true,就会创建这个bean,否则这个bean会被忽略.如@Conditional(Student.class),此时我们需要在Student类种实现condition接口,从写里面的match方法.如果放回true就会创建bean,否则反之public class CDPlayImpl implements CDPlay, Condition { @Override public void play() { System.out.println("成功注入"); } @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { return true; } }
- 处理自动装配的歧义性
也就是定义的bean有多个实现,spring会无从选择哪个bean,只好宣告失败并抛出异常
- 标示首选的bean
使用@primary.@primary和@component组合用在组件扫描的bean上,也可以用在和@bean组合.称之为首选bean. - 限定自动装配bean
当首选bean超过一个时,我们没有其他办法进一步缩小可选范围,
@qualifier注解是使用限定符的主要方式,他可以与@autowired和@inject协同使用,在注入的时候指定要注入进去的是哪个bean,
注意:指定的@qualifier("bean的id"),并且首字母是小写,创建自定义的限定符如@component@qualifier("code"). - 使用自定义的限定符注解,作用于当出现两个及两个以上同样的限定符时使用(又出现了歧义).
- bean的作用域
- spring定义了多种作用域,可以基于这些作用域创建bean,包括
单例(默认情况下是单列),
原型(每次注入或者通过上下文获取都会创建一个新的bean实例),
会话(每一次会话创建一个bean),
请求(每一个请求创建一个bean)
如果要使用其他作用域,要使用@scope注解,他可以和@component和@bean一起使用 - 使用会话和请求作用域
12.运行时值注入
spring提供了两种在运行时求值的方式:属性占位符和spring表达式语言
- 注入外部的值
属性占位符:@PropertySource("classpath:xxx.properties") //声明属性源
@Envioment ev
参数如(ev.getProperty(disc.aa),ev.getProperty(disc.bb))
在properties的文件中内容大致如下:disc.aa=xxxx disc.bb=xxxx
这个属性文件会被加载到spring的环境中,稍后会从这里检索属性 - 深入学习spring的environment
environment的getProperty有四中重载方法以及getRequiredProperty()(必须定义属性参数)
除此environment还可以检查哪些profile处于激活状态等 getActiveProfiles()
解析外部属性能够将值的处理延迟到运行时但是他的根据点在于根据民称解析来自于spring environment和属性源的属性,而是spring表达式语言提供一种更为通用的方式在运行时计算要注入的值 - 使用spring表达式语言进行装配
spel的特性:使用bean的id来引用bean;
调用方法和访问对象的属性
对值进行算术,关系和逻辑运算
正则表达式
集合操作
spel所支持的基础表示式
表示字面值:#{3.14} ,#{"hello"}
引用bean,属性和方法:#{beanId},#{beanId.attr}, 调用bean的方法#{beanId.xxx()},,#{beanid.xxx()?.toString()}[如果xxx()返回的String是null的话,通过?,就不会在执行TOString()方法了]
在表达式中使用类型:使用T()这个关键的运算符 如 :T(Math).random() //这里T()得到是是一个class对象,也就是math
T()的真正价值在于可以访问到目标类型的常量和静态方法 如 T(Math).PI - spel运算符
算术,比较,逻辑,条件,正则都可以.同java一样
三元运算符的一个常用场景是检查null值,并使用一个默认值来代替null - 计算正则表达式
如#{admin.email matches '[a-Az-A0._%]+\\/com'} - 计算集合
#{sing.song[4].title}
也可以从String中获取一个字符 如 #{'hello'[3]}