(*告知读者:本文章内容属于本人学习中笔记,若有错误或不当之处欢迎留言指出)
SpringBoot基于Spring开发应用程序,那么学习SpringBoot就不能少去了解Spring的知识
一.Spring的两大核心理念:控制反转(Inversion of Control)和面向切面编程(Aspect Oriented Programming)
1.控制反转(Ioc):spring管理bean的容器,可以理解为Ioc容器,例如Web容器一样的东西。它有两个基本功能:
a.通过描述管理Bean,包括发布并且获取Bean
b.通过描述来完成Bean之间的依赖关系,则过程叫做依赖注入(Dependency Injection)
1.1 所有Ioc容器都需要实现的一个顶级接口BeanFactory,它的源码如下:
public interface BeanFactory {
// 前缀
String FACTORY_BEAN_PREFIX = "&";
// 多个获取Bean的方法
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
// 是否包含Bean
boolean containsBean(String var1);
// 是否是单例模式
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
// 是否是原型
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
// 是否类型匹配
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
// 获取Bean的类型
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
// 获取Bean的别名
String[] getAliases(String var1);
}
1.2 接下来就是怎样在Ioc容器里装配Bean,SpringBoot基于注解开发应用程序,所以在此也用注解实现装配Bean
a.通过@Bean注解装配
/**
* name的值相当于在Ioc容器为Bean取的名字
* 在Ioc容器可通过getBean(name)来获取Bean
*/
@Bean(name="myUser")
public User getUser(){
User user = new User();
user.setId(1);
user.setName("张三");
return user;
}
b.通过@Component注解装配
@Component("myUser")
public class User {
@Value("123")
private int id;
@Value("李四")
private String name;
}
c.还可通过@ComponentScan注解定义扫描的包 ,注解源码如下:
// 表示生命周期在运行时有效
@Retention(RetentionPolicy.RUNTIME)
// 表示该注解用于什么上面,此值表示用在类上
@Target({ElementType.TYPE})
@Documented
// 是否可重复使用
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
// 定义扫描的包
@AliasFor("basePackages")
String[] value() default {};
// 定义扫描的包 value与basePackages同作用
@AliasFor("value")
String[] basePackages() default {};
// 定义扫描的类
Class<?>[] basePackageClasses() default {};
// Bean name生成器
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
// 作用域解析器
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
// 作用域代理模式
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default "**/*.class";
// 是否启用默认的过滤器
boolean useDefaultFilters() default true;
// 当满足过滤器条件时扫描
ComponentScan.Filter[] includeFilters() default {};
// 不满足过滤器条件时扫描
ComponentScan.Filter[] excludeFilters() default {};
// 是否延迟初始化 懒加载
boolean lazyInit() default false;
// 定义过滤器
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
// 过滤器类型 可以按注解或者正则式过滤
FilterType type() default FilterType.ANNOTATION;
// 过滤的类
@AliasFor("classes")
Class<?>[] value() default {};
// 过滤的类
@AliasFor("value")
Class<?>[] classes() default {};
// 匹配方式过滤
String[] pattern() default {};
}
}
1.3 Ioc的另外一个功能,依赖注入(Dependency Injection)
a.注解@Autowired
public class User {
@Autowired
private MobilePhone mobilePhone;
public useMobilePhone(){
this.mobilePhone.use();
}
public static void main(String[] args) {
User user = new User();
user.useMobilePhone();
}
}
public interface MobilePhone {
void use();
}
@Component
public class HUAWEIMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用华为手机");
}
}
@Component
public class AppleMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用苹果手机");
}
}
@Component
public class XiaoMIMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用小米手机");
}
}
此时手机有不同类型的手机,通过@Autowired注解进行注入就会报错
此时可引入注解@Primary和注解@Qualifier解决,代码如下
@Component
//此注解表示优先注入此类型的Bean
@Primary
public class HUAWEIMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用华为手机");
}
}
@Component
public class AppleMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用苹果手机");
}
}
@Component
public class XiaoMIMobilePhone implements MobilePhone {
public void use(){
System.out.println("使用小米手机");
}
}
但是三个类型都加@Primary注解则还是会报错,则@Qualifier派上用场,此注解可通过Bean的名字进行注入,
例如:@Qualifier("appleMobilePhone")
public class User {
@Autowired
@Qualifier("appleMobilePhone")
private MobilePhone mobilePhone;
public useMobilePhone(){
this.mobilePhone.use();
}
public static void main(String[] args) {
User user = new User();
user.useMobilePhone();
}
}
总结:Ioc容器为Spring管理Bean的容器,用@Bean,@Component,@ComponentScan注解可装配你的Bean。
@Autowired用来实现依赖注入,@Primary和@Qualifier来消除歧义性