Spring5.0 注解与功能整理

spring 注解容器

// xml容器与注解容器对比
//*******************
// 使用传统的xml启动spring
ApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object bean = xmlApplicationContext.getBean("beanName");

// 使用注解启动Spring
// 配置类 SpringConfig.class 需要带上@Configuration 注解,作用上相当于beans.xml。
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
Object bean = xmlApplicationContext.getBean("beanName");
复制代码

主要的注解与功能

注解 作用
@Configuration 注解配置类,相当于bean.xml 的作用
@Bean 创建一个Bean,一般用于加载第三方class
@Service 创建一个Bean,加载自己class
@Controller 创建一个Bean,加载自己class
@Repository 创建一个Bean,加载自己class
@Component 创建一个Bean,加载自己class,Spring 5.0 开始,可以使@Indexed
@ComponentScan 扫描指定包路径,将Bean组件加入容器。可以配置引入规则、排除规则等
@Scope Bean的作用范围,配置Bean是单实例,还是多实例
@Lazy 懒加载,只对单例Bean有效果
@Conditional 按照一定条件对Bean 进行判断,将满足条件的Bean加入到容器
@Import 快速向容器中导入其他组件(Bean)
FactoryBean 通过实现FactoryBean 接口的方式,创建一个Bean
initMethod @Bean 的属性,初始化完成之后触发的操作
destroyMethod @Bean 的属性,Bean销毁后触发的操作
@PostConstruct 在Bean 创建、属性赋值完成后,执行初始化
@PreDestroy 在容器销毁Bean 之前执行操作
BeanPostProcessor 每一个Bean 在初始之前,都会调用BeanPostProcessor.postProcessBeforeInitialization,
每一个Bean 在初始之后,都会调用BeanPostProcessor.postProcessAfterInitialization,
Spring中很多功能都是通过此方法实现。
例如: ApplicationContextAware,通过ApplicationContextAwareProcessor实现,
@Autowired,通过AutowiredAnnotationBeanPostProcessor 实现
xxxAware 一些功能性接口,实现相应的接口来获取、定制Spring服务。
例如:ApplicationContextAware, 可以获取IOC容器
@Value 给Bean 属性赋值
@Autowired Spring依赖注入,顺序是:类型->名称
@Qualifier 指定某个Bean 进行注入
@Primary 设置Spring自动装配时,首选的Bean
@Resources 符合JSR250 标准的依赖注入,通过名称匹配
@Inject 符合JSR330 标准的依赖注入,和Autowired 基本一样
@Profile 通过环境参数配置Bean的注入

Bean 的创建与注册

@ComponentScan

// @ComponentScan 可以将带有@Bean、@Service、@Controller、@Repository、@Component注解的对象加入到容器(IOC)
@ComponentScan(value = "com.xxx.statement")

// @ComponentScans 支持多个ComponentScan 注解配置
@ComponentScans(
        value = {
                @ComponentScan(value = "com.xxx.statement", includeFilters = {}),
                @ComponentScan(value = "com.xxx.statement", excludeFilters = {})
        })

// ******** 使用不同的方式配置添加、排查规则 *********
// FilterType.ANNOTATION 按照注解排除
// FilterType.ASSIGNABLE_TYPE 按照给定的类型
// FilterType.ASPECTJ ASPECTJ表达式
// FilterType.REGEX 正则表达式
// FilterType.CUSTOM 自定义规则,必须实现 TypeFilter接口。

// @ComponentScan 根据规则排除某些Bean
@ComponentScan(
        value = "com.xxx.statement",
        useDefaultFilters = true,
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        })

// @ComponentScan 根据规则加载某些Bean
@ComponentScan(
        value = "com.xxx.statement",
        useDefaultFilters = false,
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        }
  
// FilterType.CUSTOM 自定义规则,必须实现 TypeFilter接口。
public class MyComponentScanFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正则扫描的类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类的路径
        Resource resource = metadataReader.getResource();

        //获取其他bean信息
        MetadataReader otherBean = metadataReaderFactory.getMetadataReader("className");
        
        return false;
    }}
  


复制代码

@Scope

// @Scop bean的作用域
// 多实例
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
// 单例
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) 
复制代码

@Lazy

//@Lazy 懒加载,只针对于单实例的Bean
@Lazy
复制代码

@Conditional

// 按照一定条件对Bean 进行判断,将满足条件的Bean加入到容器
@Bean
@Conditional(value = MyCondition.class)
public MyBean bean() {
    return new MyBean();
}

// 需要实现Condition接口
public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //可以获取到容器的上下文
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        ClassLoader classLoader = context.getClassLoader();
        Environment environment = context.getEnvironment();

        //可以获取Bean的注解信息
        MergedAnnotations annotations = metadata.getAnnotations();
        return false;
    }
}
复制代码

@Import

//快速向容器中导入其他组件(Bean)
//********* 导入方式一 *********
@Configuration
@Import({MyBean.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class SpringConfig {
}

//********* 导入方式二 *********
// 使用ImportSelector 返回需要导入的组件的全类名
// 需要实现ImportSelector 接口
public class MyImportSelector implements ImportSelector {
  	//importingClassMetadata 返回标记了@Import类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.xxx.statement.spring.test.MyBean"};
    }
}

//********* 导入方式三 *********
// 使用ImportBeanDefinitionRegistrar 将Bean注册到容器
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata 标记了Import 的class 的注解元数据
     * @param registry Bean注册工具,用此register 将bean 注册到容器
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //注册一个Bean
        BeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);
        registry.registerBeanDefinition("myBean", beanDefinition);
    }
}


复制代码

FactoryBean

//使用FactoryBean 接口创建Bean
//需要实现FactoryBean 接口
public class MyBeanFactoryBean implements FactoryBean<MyBean> {

    /**
     * 获取Bean的实例
     */
    @Override
    public MyBean getObject() throws Exception {
        return new MyBean();
    }

    /**
     * 获取Bean的类型
     */
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }

    /**
     * 是否是单例
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

//在初始化Bean的时候,调用FactoryBean,会创建Bean的实例。
@Bean
public MyBeanFactoryBean factoryBean() {
    return new MyBeanFactoryBean();
}
复制代码

Bean 的生命周期

initMethod, destroyMethod

@Bean(initMethod = "init", destroyMethod = "destroy")
public MyBean bean() {
    return new MyBean();
}
复制代码

InitializingBean, DisposableBean

//使用InitializingBean, DisposableBean 接口初始化、销毁Bean
public class MyBean implements InitializingBean, DisposableBean {

    @Override
    public void destroy() throws Exception {

    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}
复制代码

@PostConstruct, @PreDestroy

//使用@PostConstruct, @PreDestroy 在初始化之后、销毁之前做操作
//@PostConstruct 在Bean 创建、属性赋值完成后,执行初始化
//@PreDestroy 在容器销毁Bean 之前执行操作
public class MyBean{
    @PostConstruct
    public void init() {

    }

    @PreDestroy
    public void destroy() {

    }
}
复制代码

BeanPostProcessor

// BeanPostProcessor 在Bean 初始化前后执行操作
// 实现BeanPostProcessor 接口,
// 每一个Bean 在初始之前,都会调用postProcessBeforeInitialization
// 每一个Bean 在初始之后,都会调用postProcessAfterInitialization
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}

/**
 * 源码概览:***AbstractAutowireCapableBeanFactory***
 */
//Bean属性赋值
populateBean(beanName, mbd, instanceWrapper); 
//赋值之后开始初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);  
//初始化分为三步
// 1、前置处理(调用:postProcessBeforeInitialization)
Bean wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 2、反射创建Bean
invokeInitMethods(beanName, wrappedBean, mbd);	 
// 3、后置处理(调用:postProcessAfterInitialization)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 
**/
复制代码

xxxAware

//Spring 提供了许多Aware 接口,用于容器扩展和定制
//例如获取ApplicationContext 对象
public class SpringConfig implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

//Aware功能也是通过BeanPostProcessor 实现
class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

}
复制代码

Aware 接口列表:

Aware 功能描述
ApplicationContextAware 获取ApplicationContext(IOC)容器
ApplicationEventPublisherAware 获取SpringEvent 事件发布器
EmbeddedValueResolverAware 获取配置文件解析器,从配置文件中取值
MessageSourceAware 获取国际化工具,从国际化配置文件中获取不同的数据
ResourceLoaderAware 获取资源文件的工具,通过资源路径检索外部资源
EnvironmentAware 获取环境配置,环境参数

Bean 属性赋值

@Value

@Value 用于给属性赋值

  • 可以写固定值赋值
  • 可以使用SpEL 表达式赋值 “#{}”
  • 可以读取配置文件的数据赋值 “${}”
// 固定值
public class MyBean{
    @Value("测试")
    private String name;
}
复制代码
// 获取配置文件中的值
@PropertySource("classpath:test.properties")
public class MyBean{
    @Value("${name}")
    private String name;
}
复制代码

自动装配

@Autowired

//@Autowired 通过AutowiredAnnotationBeanPostProcessor 来实现自动注入
//@Autowired 注入的优先级,类型>属性名
@Service
public class MyService {
    //可以标注在属性上
    @Autowired
    private MyBean myBean;

    //可以标注在构造函数上
    @Autowired
    public MyService(MyBean myBean) {
        this.myBean = myBean;
    }

    //可以标注在方法上
    @Autowired 
    public void setMyBean(MyBean myBean) {
        this.myBean = myBean;
    }
  
    //可以标注在参数上
    public void setMyBean(@Autowired MyBean myBean) {
        this.myBean = myBean;
    }
}
复制代码

@Qualifier

//指定Bean的注入类型
@Service
public class MyService {
    @Qualifier("myBean")
    @Autowired
    private MyBean myBean;
}
复制代码

@Primary

// 设置Spring自动装配时,首选的Bean
@Primary
public class MyBean {
}
复制代码

@Resources, @Inject

// @Resources 是JSR250 支持的注解,此注解是按照名称自动装配的
// @Inject 是JSR330 支持的注解,需要导入inject 包,此注解除了没有required 属性,其他功能与Autowired 一样。
复制代码

Aware

实现xxxAware 接口,在创建对象的时候,会自动注入相关组件

public class MyAware implements ApplicationContextAware {
    private ApplicationContext applicationContext;
            
    //ApplicationContext 参数就是自动注入的对象
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
复制代码

@Profile

//根据当前环境, 动态的切换加载组件
//切换环境:
//    1、使用参数:-Dspring.profiles.active=test
//    2、在environment 里面设置环境
//           applicationContext.getEnvironment().setActiveProfiles("test", "prod")
@Configuration
public class MyProfileConfig {

    @Profile(value = "default")
    private MyBean bean1() {
        return new MyBean("dev");
    }

    @Profile(value = "test")
    private MyBean bean2() {
        return new MyBean("test");
    }

    @Profile(value = "prod")
    private MyBean bean3() {
        return new MyBean("prod");
    }

}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享