在学习SpringBoot之前,有几个Spring的重要的基础概念需要提一下,SpringBoot对这些基础概念做进一步的封装,完成自动配置。首先就是Spring的控制反转IOC,由于SpringBoot不建议使用XML,因此本小节旨在关注全注解下的Spring IoC。
其中比较重要的是第二点与第三点:第二点里的注解要么常用于业务开发,要么在源码里常见;第四点的@Autowired
需要关注。
注:在说明注解时,第一点加粗为注解中文含义,第二点为一般加在哪身上,缩进或代码块为示例,如:
@注解
中文含义
加在哪
其他……
语句示例
//代码示例
Spring的IoC容器其实就是一个Bean管理的容器。
所有的IoC容器都要实现顶层接口BeanFactory
(Bean工厂),该工厂定义了一些操作Bean实例的基本方法,源码如下:
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);
//Bean是否单例
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
//Bean是否原型
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;
//获取Bean别名
@Nullable
Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
从上述源码可知,顶层接口定义了一些基本方法,其中需要注意的点有:
isSingleton
方法判断Bean是否在Spring IoC中为单例。默认情况下Bean都是以单例存在,即:调用getBean方法返回同一个对象;(详情见第五点Bean的作用域)isPrototype
方法判断原型,若返回true,则调用getBean方法时IoC会创建一个新的Bean返回,与Bean的作用域相关;(详情见第五点Bean的作用域)在BeanFactory基础上,有一些高级接口,可以用个实现接口完成定制化操作。
Spring IoC接口设计如下:
需要关注ApplicationContext
接口,其的实现类有:
FileSystemXmlApplicationContext
: 表示从文件绝对路径加载配置文件;
ClassPathXmlApplicationContext
:表示 从classpath下加载配置文件(适合于相对路径方式加载) 。
//Spring里常用获取Bean的方法
@Test
public void testBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Orders orders = context.getBean("orders", Orders.class);
}
通常意义上讲的Spring IoC控制反转就是往容器中添加组件过程,针对添加的组件类型不同,有相应不同的注解实现。该点下很多注解在源码里常见。
注解
功能介绍
@Repository
数据库层组件,常用于DAO层;
@Service
业务逻辑组件,常用于业务逻辑层;
@Controller
控制器,常用于页面展示层;控制器默认方法返回的是页面跳转;
@RestController
REST风格控制器, 常用于响应字符串,是@ResponseBody和@Controller的组合注解;默认方法返回的是json数据;
@Component
注册组件,常用于POJO层。可以配置Bean的名称,如@Component("XXX");不配置时Ioc容器将类名第一个字母小写,其他不变放入容器中;
@Bean
给容器注册组件。常用于第三方包,源码里常见。
@ComponentScan:
@ComponentScan(basePackages = {"com.dlhjw"})
@ComponentScan(basePackages = "com.dlhjw.*", excludeFilters = {@Filter{classes = {Service.class}}})
@Import
@Import({User.class, DBHelper.class})
:给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名@Import
高级用法:https://www.bilibili.com/video/BV1gW411W7wy?p=8@Conditional
Full模式与Lite模式针对spring配置而言的,和xml配置无关。单实例可以理解成每次从IoC容器中取出同一个对象,原型则对应每次取出时都会new一个新对象。
Full模式(默认,单实例):
标注有@Configuration
或者@Configuration(proxyBeanMethods = true)
的类被称为Full模式的配置类;
proxyBeanMethods
:代理bean的方法;单实例是IoC容器启动时就会去实例化bean并添加到容器当中去,每次获取都是从容器中获取同一个对象;
单例模式能有效避免Lite模式下的错误。性能没有Lite模式好;
Lite模式(多实例):
@Component
注解;@ComponentScan
注解;@Import
注解;@ImportResource
注解;@Bean
方法;@Configuration(proxyBeanMethods = false)
注解;依赖注入讨论的是Bean之间的依赖关系,例如一个类里包含另一个类。上面第二点讨论的是添加组件,如果把它理解成创建对象的话,那么依赖注入就是获取这个对象并使用。依赖注入的前提是往容器添加组件,也就是说只有容器中有这个组件,才能取出来使用。
@Autowired
@Autowired(required = false)
@Primary
@Quelifier
限定注入
与@Autowired一同使用;
配置需要注入的名称即可;
@Autowired //根据类型Animal
@Quelifier("dog") //根据名称dog
private Animal animal;
大致分为Bean的定义、Bean的初始化、Bean的生存期和Bean的销毁是个过程。
Bean的生命周期
在@ComponentScan注解里对配置项lazyInit配置true可以对Bean的初始化延迟,即Spring不会在发布Bean定义后马上进行实例化与依赖注入;
@ComponentScan(lazyInit = true)
可以通过实现上图的接口,进行自定义Bean的生命周期各项属性;
注解@PostConstruct
定义了初始化方法,注解@PreDestroy
定义了销毁方法;
这里指如何给Bean的属性赋值
@Value
属性值
常用于属性与方法上;
可以使用Spring EL表达式对需要配置的属性进行运算;
${......}
:表示占位符,读取上下文(application配置文件)的属性值进行装配;#{......}
:表示启用Spring表达式,具有运算功能;T(......)
:表示引入类;表示给Bean赋值,可以用${xxx}占位符读取application配置文件的内容;
//获取application里的database.driverName值装配进方法里
@Value("${database.driverName}")
private String driverName;
//赋值字符串,同理可以赋值整形、浮点数等
@Value("#{'赋值字符串'}")
private String str;
//str后跟着?,表示判断str是否为空,不为空才执行toUpperCase方法
@Value("#{beanName.str?.toUpperCase()}")
private String otherBeanProp;
//字符串比较
@Value("#{beanName.str eq 'SpringBoot'}")
private boolean strFlag;
//调用方法,System是Java默认加载的包,不用写全类名;其他包要
@Value("#{T(System).currentTimeMillis()}")
private Long initTime;
@ConfigurationProperties
配置属性
常标注在类上;
解决@Value过多问题;
@ConfigurationProperties(“database”)
public class DataBaseProperties{
}
@PropertySource
@PropertySource(value={"classpath:jdbc.properties"}, ignoreResourceNotFound=true)
在Bean的作用域里,常用的是以下加粗的四种。前面IoC容器里讨论的isSingleton与isPrototype方法本质上是作用域的问题。
application
域而言,完全可以使用单例替代;@Scope
作用域
常加在类上;
用于修改作用域;
ConfigurableBeanFactory
仅提供SCOPE_PROTOTYPE (原型)和SCOPE_SINGLETON(单例)两种;
在SpringMVC环境中,WebApplicationContext
提供SCOPE_REQUEST(请求)、SCOPE_SESSION(会话)、SCOPE_APPLICATION(应用)三种。
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ScopeBean{
}
//在同一个请求范围内去获取Bean时,只会共用一个Bean,第二次请求会产生新的Bean
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class ScopeBean{
}
在实际开发中,项目往往需要在开发环境、测试环境、准生产环境和生产环境中切换,Spring提供了Profile机制,方便在各个环境间切换。
@Profile
配置切换
常用于不同环境下需要不用配置的方法或类上;
可以在application中配置两个参数修改Profile机制,spring.profiles.active
与spring.profiles.default
,当这两个属性都没配置情况下,Spring不会启动Profile机制。其中,前者优先级高。
虽然SpringBoot不建议使用XML来进行属性配置,但在某些情况下我们又不得不使用XML来进行配置,如:Dubbo框架基于Spring的XML方式进行开发。需要将其引入才能作用。
@ImportResources
导入资源
常用于需要XML装配是配置类上;
@ImportResources(value = {" classpath:spring-other.xml"})
public class AppConfig{
}
新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章