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