spring 常用注解 原理 逻辑 代码演示
一、组件注册
1.1-spring注解驱动开发
1.2-组件注册 @Configuration
// spring依赖 maven repository中按照版本查询
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
//junit依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
注意
如果创建beans.xml没有如下信息,可通过项目->右键->add framework Support->勾选spring后,resource包下右键new->XML Configuration File-> Spring Config即可
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
1.3-组件注册 Configuration、Bean、ComponentScan(s)、TypeFilter
1.3.1 Configuration Bean
//创建person类
package com.liuting.pojo;
public class Person {
private String name;
private String age;
public Person() {
}
public Person(String name, String age) {
System.out.println("person constructor........");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
public void init(){
System.out.println("person.....init.....");
}
public void destroy(){
System.out.println("person.....destroy.....");
}
}
//配置类
package com.liuting.config;
import com.liuting.pojo.Person;
import org.springframework.context.annotation.*;
//配置类==配置文件
@Configuration //告诉spring这是一个配置类
public class MainConfig {
//给容器中注册一个Bean:类型为返回值类型;id默认是方法名作为id
@Bean
public Person person(){
return new Person("lt","12");
}
//通过@Bean注解的value属性可指定beand的名称
@Bean(value="person02")
public Person person(){
return new Person("lt","12");
}
}
//测试类 通过AnnotationConfigApplicationContext注解式的config,它传入的就是这个配置类。相当于是传配置类的位置。
package com.liuting;
import com.liuting.config.MainConfig;
import com.liuting.pojo.Person;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
//通过类型获取容器中的对象
Person person01 = applicationContext.getBean(Person.class);
Person person02 = (Person) applicationContext.getBean("person");
System.out.println(person01);
System.out.println(person02);
//通过getBeanDefinitionNames()方法可以获取容器中组件的所有名称
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (int i = 0; i < beanDefinitionNames.length; i++) {
System.out.println(beanDefinitionNames[i]);
}
}
}
==============================测试结果(1)===================
Person{name='lt', age='12'}
Person{name='lt', age='12'}
==============================测试结果(2)===================
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
1.3.1 ComponentScan(s):注解扫描包设置,包扫描、只要标注了@Controller、@Service、@Repository、@Component,都会被自动扫描加入容器中
@Configuration
//注解扫描包设置
//excludeFilters = Filter[] 指定扫描的时候按照规则排除哪些规则
//includeFilters = Filter[] 指定扫描的时候只需要包含哪些组件
//useDefaultFilters 默认为true,加载所有组件
@ComponentScan(value = "com.liuting.*",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class})})
public class MainConfig {
@Bean
@Scope()
public Person person(){
return new Person("lt","12");
}
}
注意
package org.springframework.context.annotation;
//过滤类型
public enum FilterType {
//注解
ANNOTATION,
//按照给定的类型
ASSIGNABLE_TYPE,
//使用ASPECTJ表达式(不太常用)
ASPECTJ,
//使用正则表达式
REGEX,
//使用自定义,实现TypeFilter
CUSTOM;
private FilterType() {
}
}
package com.liuting.typeFilter;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
public class MyTypeFilter implements TypeFilter {
/**
* @param metadataReader the metadata reader for the target class 读取到当前正在扫描类信息
* @param metadataReaderFactory a factory for obtaining metadata readers :获取到其他类的任何信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描到类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类路径)
metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("---->"+className);
//true匹配成功,false匹配失败
return false;
}
}
1.3.2 Scope:默认是单实例的
* ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype 多实例
* ConfigurableBeanFactory#SCOPE_SINGLETON singleton 单实例(默认值)
* org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request 同一次请求创建一个实例
* org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session 同一个session创建一个实例
1.3.3 @Lazy:
- 单实例bean,默认在容器启动的时候创建对象
- 懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化
package com.liuting.config;
import com.liuting.pojo.Person;
import com.liuting.typeFilter.MyTypeFilter;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan(value = "com.liuting.*",excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})})
@ComponentScan
public class MainConfig {
@Bean
@Lazy//第一次使用(获取)Bean创建对象,并初始化
public Person person(){
return new Person("lt","12");
}
}
1.3.3 @Import:
/**
* 给容器中注册组件:
* 1) 包扫描+组件标注注解 (@Controller/@Service/@Repository/@Component)[自己写的]
* 2) @Bean[导入的第三方包里面的组件],但是它比较麻烦(需要return等)
* 3) @Import[快速给容器导入一个组件]
*/
二、生命周期
2.1-生命周期 @Bean指定初始化和销毁方法
#带init(),destroy()实体类
package com.liuting.pojo;
import org.springframework.stereotype.Repository;
@Repository
public class Person {
public Person() {
System.out.println("person...constructor");
}
public void init(){
System.out.println("person.....init.....");
}
public void destroy(){
System.out.println("person.....destroy.....");
}
}
package com.liuting.config;
import com.liuting.pojo.Person;
import com.liuting.typeFilter.MyTypeFilter;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Repository;
@Configuration
@ComponentScan(value = "com.liuting.*",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Repository.class})},useDefaultFilters = false)
public class MainConfig {
//将init()、destroy()设置到bean中
@Bean(initMethod = "init",destroyMethod = "destroy")
public Person person(){
return new Person();
}
}
* bean的生命周期:
* bean创建---初始化---销毁的过程
* 容器管理bean的生命周期:
* 我们可以自定义初始化和销毁方法;容器在 bean进行到当前生命周期的时候调用我们自定义的初始化和销毁方式
*构造(对象创建)
* 单实例:在容器启动的时候创建对象
* 多实例:在每次获取的时候创建对象
*初始化:
* 对象创建完成,并赋值好,调用初始化方法。。。
*销毁:
* 单实例:容器关闭的时候
* 多实例:容器不会管理这个bean,容器不会调用销毁方法;需要手动调用
* 1)、指定初始化和销毁方法:
* 指定init-method和destroy-method方法
2.2-生命周期 InitializingBean和DisposableBean
package com.liuting.pojo;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Repository;
@Repository
public class Person implements InitializingBean, DisposableBean {
public Person() {
System.out.println("person...constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("person.....afterPropertiesSet.....");
}
@Override
public void destroy() throws Exception {
System.out.println("person.....destroy.....");
}
}
2.3-生命周期 @PostConstrct和@PreDestroy
@PostConstruct:在bean创建完成并且属性赋值完成:来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
2.4-生命周期 BeanPostProcessor(后置处理器)
BeanPostProcessor【interface】,bean的后置处理器:
-
在bean初始化前后进行一些处理工作:
-
postProcessBeforeInitialization:在初始化之前工作
-
postProcessAfterInitialization:在初始化之后工作
2.3-生命周期 @PostConstrct和@PreDestroy
@PostConstruct:在bean创建完成并且属性赋值完成:来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
[外链图片转存中…(img-JcmwRd0B-1611824474244)]
2.4-生命周期 BeanPostProcessor(后置处理器)
BeanPostProcessor【interface】,bean的后置处理器:
-
在bean初始化前后进行一些处理工作:
-
postProcessBeforeInitialization:在初始化之前工作
-
postProcessAfterInitialization:在初始化之后工作