前言

最近在看 B 站颜群老师的课程,Javaweb>spring>springMVC>mybatis>spring 高级,一路走来,跌跌撞撞,发现 spring 也不过尔尔,说白了,spring 就是想尽办法将 new 做的更简单,更完美,更可配置。

Spring 的一个核心功能是 IOC,就是将 Bean 初始化加载到容器中,Bean 是如何加载到容器的,可以使用 Spring 注解方式或者 Spring XML 配置方式。

Spring 注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率!

注解本身是没有功能的,和 xml 一样,注解和 xml 都是一种元数据,元数据即解释数据的数据,也就是所谓的配置。

xml 和注解的最佳实践:

  • xml 用来管理 bean;
  • 注解只负责完成属性的注入;

使用注解唯一需要注意的就是,必须开启注解的支持:

1
2
3
//扫描指定包下的全部的标有@Component的类,并注册成bean.
<context:component-scan base-package="com.guo"></context:component-scan>
<context:annotation-config/>

Spring 的常用注解

给容器中注入组件

包扫描+组件标注注解

@Component:泛指各种组件

@Controller、@Service、@Repository都可以称为@Component

@Controller:控制层

@Service:业务层

@Repository:数据访问层

@Bean: 导入第三方包里面的注解

@Import(要导入到容器中的组件);

1
2
3
4
5
6
7
8
9
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
@Scope("prototype")
@Bean("person")
public Person person() {
System.out.println("我是Person");
return new Person("素小暖",25);
}
}

@ImportSelector:返回需要导入的组件的全类名数组;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

/*
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
* 把所有需要添加到容器中的bean,调用BeanDefinitionRegistry.registerBeanDefinition手动注入
*
* */
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
if(definition && definition2){
//指定bean定义信息(bean的类型,bean的scope)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个bean,指定bean名
registry.registerBeanDefinition("rainBow",rootBeanDefinition);
}
}
}

使用 spring 提供的FactoryBean(工厂 Bean)

  • 默认获取到的是工厂Bean调用getObject创建的对象
  • 要获取工厂Bean本身,需要在 id 前面加一个&
1
2
3
4
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//创建一个spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,并将Color添加到容器中
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean,getObject()");
return new Color();
}

public Class<?> getObjectType() {
return Color.class;
}

public boolean isSingleton() {
return false;
}
}

注入 bean 的注解

@Autowired:由 bean 提供

  • @Autowired 可以作用在变量、setter 方法、构造函数上;
  • 有个属性为 required,可以配置为 false;

@Inject:由 JSR-330 提供

  • @Inject 用法和@Autowired 一样。

@Resource:由 JSR-250 提供

@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的,@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject 和@Name 一起使用。

@Primary

spring进行自动装配的时候,默认使用首选的bean,和@Qualifier一个效果。

@JsonIgnore

  1. 作用: 在 json 序列化时将 java bean 中的一些属性忽略掉,序列化和反序列化都受影响。
  2. 使用方法: 一般标记在属性或者方法上,返回的 json 数据即不包含该属性。
  3. 注解失效:如果注解失效,可能是因为你使用的是 fastJson,尝试使用对应的注解来忽略字段,注解为:@JSONField(serialize = false),使用方法一样。

初始化和销毁方法

  1. 通过@Bean(initMethod=”init”,destoryMethod=”destory”)方法
  2. 通过 bean 实现 InitializingBean 来定义初始化逻辑,DisposableBean 定义销毁逻辑
  3. 可以使用 JSR250:@PostConstruct:初始化方法;@PreDestory:销毁方法。
  4. BeanPostProcessor:bean 的后置处理器,在 bean 初始化前后进行一些处理工作
  5. postProcessBeforeInitialization:在初始化之前工作;
  6. postProcessAfterInitialization:在初始化工作之后工作;

Java 配置类相关注解

@Configuration

声明当前类为配置类;

@Bean

注解在方法上,声明当前方法的返回值为一个 bean,替代 xml 中的方式;

@ComponentScan

用于对Component进行扫描;

切面(AOP)相关注解

Spring AOP 详细介绍

Spring 支持AspectJ的注解式切面编程。

@Aspect 声明一个切面

@After 在方法执行之后执行(方法上)

@Before 在方法执行之前执行(方法上)

@Around 在方法执行之前与之后执行(方法上)

@PointCut 声明切点

在 java 配置类中使用@EnableAspectJAutoProxy注解开启SpringAspectJ代理的支持

@Bean 的属性支持

@Scope设置类型包括:

设置 Spring 容器如何新建 Bean 实例(方法上,得有@Bean

Singleton

(单例,一个 Spring 容器中只有一个 bean 实例,默认模式),

Protetype

(每次调用新建一个 bean),

Request

(web 项目中,给每个 http request 新建一个 bean),

Session

(web 项目中,给每个 http session 新建一个 bean),

GlobalSession

(给每一个 global http session 新建一个 Bean 实例)

@Value 注解

支持如下方式的注入:

  • 注入普通字符
  • 注入操作系统属性
  • 注入表达式结果
  • 注入其它 bean 属性
  • 注入文件资源
  • 注入网站资源
  • 注入配置文件

@Value三种情况的用法。

  1. ${}是去找外部配置的参数,将值赋过来
  2. #{}是 SpEL 表达式,去寻找对应变量的内容
  3. #{}直接写字符串就是将字符串的值注入进去

环境切换

@Profile

指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件。

@Conditional

通过实现 Condition 接口,并重写 matches 方法,从而决定该 bean 是否被实例化。

异步相关

@EnableAsync

配置类中通过此注解开启对异步任务的支持;

@Async

在实际执行的 bean 方法使用该注解来声明其是一个异步任务(方法上或类上所有的方法都将异步,需要@EnableAsync 开启异步任务)

定时任务相关

@EnableScheduling

在配置类上使用,开启计划任务的支持(类上)

@Scheduled

来申明这是一个任务,包括 cron,fixDelay,fixRate 等类型(方法上,需先开启计划任务的支持)

SpringMVC 常用注解

1、@EnableWebMvc

在配置类中开启 Web MVC 的配置支持。

2、@Controller

3、@RequestMapping
用于映射 web 请求,包括访问路径和参数。

4、@ResponseBody

支持将返回值放到 response 内,而不是一个页面,通常用户返回 json 数据。

5、@RequestBody

允许 request 的参数在 request 体中,而不是在直接连接的地址后面。(放在参数前)

6、@PathVariable

用于接收路径参数,比如@RequestMapping(“/hello/{name}”)声明的路径,将注解放在参数前,即可获取该值,通常作为 Restful 的接口实现方法。

7、@RestController

该注解为一个组合注解,相当于@Controller 和@ResponseBody 的组合,注解在类上,意味着,该 Controller 的所有方法都默认加上了@ResponseBody。

8、@ControllerAdvice

全局异常处理
全局数据绑定
全局数据预处理

9、@ExceptionHandler

用于全局处理控制器里的异常。

10、@InitBinder

用来设置 WebDataBinder,WebDataBinder 用来自动绑定前台请求参数到 Model 中。

11、@ModelAttribute

(1)@ModelAttribute 注释方法

如果把@ModelAttribute 放在方法的注解上时,代表的是:该 Controller 的所有方法在调用前,先执行此@ModelAttribute 方法。可以把这个@ModelAttribute 特性,应用在 BaseController 当中,所有的 Controller 继承 BaseController,即可实现在调用 Controller 时,先执行@ModelAttribute 方法。比如权限的验证(也可以使用 Interceptor)等。

(2)@ModelAttribute 注释一个方法的参数

当作为方法的参数使用,指示的参数应该从模型中检索。如果不存在,它应该首先实例化,然后添加到模型中,一旦出现在模型中,参数字段应该从具有匹配名称的所有请求参数中填充。