Spring -> IoC 容器
IoC控制反转一种设计思想,这种设计思想是将我们之前需要自己创建和管理对象的控制权交给IoC容器来进行管理.使用IoC可以实现代码解耦
DI 依赖注入,在程序加载的时候将对象动态注入到框架中
IoC和DI的关系:IoC是一种设计思想,而DI是具体的实现
Spring 创建流程:
1.创建一个maven
2.创建一个启动类,创建ApplicationContext 对象
3.XML规定了依赖注入对象的根路径
4.依赖注入的类注释
@Controller:控制器(web逻辑处理层)前端业务交互层(参数效验)
@Service:业务逻辑层 业务处理中间类
@Component:通用组件 通用对象工具类
@Repository:数据库持久层
5.得到bean对象
1.注解:@Autowrited @Resource
2.ApplicationContent.getBean()
getBean(“类名”) 首字母大写,对应类名应该是首字母小写;如果首字母和第二字母都是大写,那么对应的类名要大写“ABC”->“ABC” “Abc” ->"abc"
getBean(类型) 得到bean
@Controller标记后,将方法给Spring进行调用,这个时候,在主函数里调用方法,可以获得哈希地址,通过Spring调用被标记Controller方法
这些注解将自己存储到Spring种,方便调用
Maven环境
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
在spring中,访问类,需要将类的首字母小写,如果前两位都是大写的,那么不需要改变
源码
/**
* Utility method to take a string and convert it to normal Java variable
* name capitalization. This normally means converting the first
* character from upper case to lower case, but in the (unusual) special
* case when there is more than one character and both the first and
* second characters are upper case, we leave it alone.
* <p>
* Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
* as "URL".
*
* @param name The string to be decapitalized.
* @return The decapitalized version of the string.
*/
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
初始化/注册Bean
1.注册Bean的方式一:类注解
在类上使用注解 @Controller , @Service , @Repository , @Component 。需要保证该类会被Spring
扫描到,这种定义方式默认会注册一个名称为类名首字母小写的Bean对象到容器中。
2.注册Bean的方式二:@Bean
当前类被 Spring 扫描到时,可以在方法上使用 @Bean 注解,通过方法返回类型,也可以定义、注册
Bean对象,默认使用方法名作为Bean的名称。
Lombok -> 自定义注解的方式,在代码编译的时候,将自定义的注解更换成JVM可以执行的方法(传统的 get 和set 方法)
3.注册Bean的方式三:@Configuration
在类被Spring扫描到时,使用 @Configuration 注解,可以注册一个配置类到容器中。配置类一般用来自定义配置某些资源。之后会在SpringMVC中用到。
依赖注入(依赖装配)
第一种方式:属性注入
当前类被 Spring 扫描到时,可以在属性上使用 @Autowired 注解,会将容器中的Bean对象装配进来。
注入指定的Bean:@Qualifier
同类型的Bean有多个时,注入该类型Bean需要指定Bean的名称:
属性名或方法参数名设置为Bean的名称
属性名或方法参数设置 @Qualifier(“名称”) 注解,注解内的字符串是Bean对象的名称
private User u1;
@Autowired
@Qualifier("user1")
public void setU1(User u1){
this.u1 = u1;
}
@Bean
public User user1(){
User user = new User();
user.setName("悟空");
user.setPassword("你这个呆子");
return user;
}
@Bean
public User user2(){
User user = new User();
user.setName("八戒");
user.setPassword("咱们还是散了吧,我回我的高老庄");
return user;
}
不用Qualifier调用方法,会出现错误
第二种方式:构造方法注入
当前类被 Spring 扫描到时,可以在构造方法上使用 @Autowired 注解,作用也是和setter方法类似,会将容器中的Bean对象注入方法参数
Bean的作用域
singleton(单例模式)
描述:该作用域下的Bean在IoC容器中只存在一个实例:获取Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是同一个对象。
场景:通常无状态的Bean使用该作用域。无状态表示Bean对象的属性状态不需要更新
备注:Spring默认选择该作用域
prototype(原型模式 @Scope)
描述:每次对该作用域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是新的对象实例。
场景:通常有状态的Bean使用该作用域
request
描述:每次http请求会创建新的Bean实例,类似于prototype
场景:一次http的请求和响应的共享Bean
备注:限定SpringMVC中使用
session
描述:在一个http session中,定义一个Bean实例
场景:用户回话的共享Bean, 比如:记录一个用户的登陆信息
备注:限定SpringMVC中使用
Bean的生命周期
对于Bean的生命周期,主要步骤为:
- 实例化Bean:通过反射调用构造方法实例化对象。
- 依赖注入:装配Bean的属性
- 实现了Aware接口的Bean,执行接口方法:如顺序执行BeanNameAware、BeanFactoryAware、
ApplicationContextAware的接口方法。 - Bean对象初始化前,循环调用实现了BeanPostProcessor接口的预初始化方法
(postProcessBeforeInitialization) - Bean对象初始化:顺序执行@PostConstruct注解方法、InitializingBean接口方法、init-method
方法 - Bean对象初始化后,循环调用实现了BeanPostProcessor接口的后初始化方法
(postProcessAfterInitialization) - 容器关闭时,执行Bean对象的销毁方法,顺序是:@PreDestroy注解方法、DisposableBean接口
方法、destroy-method