【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?

在这里插入图片描述

作者简介:zhz小白
公众号:小白的Java进阶之路
专业技能:
1、Java基础,并精通多线程的开发,熟悉JVM原理
2、熟悉Java基础,并精通多线程的开发,熟悉JVM原理,具备⼀定的线上调优经验
3、熟悉MySQL数据库调优,索引原理等,⽇志原理等,并且有出过⼀篇专栏
4、了解计算机⽹络,对TCP协议,滑动窗⼝原理等有⼀定了解
5、熟悉Spring,Spring MVC,Mybatis,阅读过部分Spring源码
6、熟悉SpringCloud Alibaba体系,阅读过Nacos,Sentinel,Seata,Dubbo,Feign,Gateway核⼼源码与设计,⼆次开发能⼒
7、熟悉消息队列(Kafka,RocketMQ)的原理与设计
8、熟悉分库分表ShardingSphere,具有真实⽣产的数据迁移经验
9、熟悉分布式缓存中间件Redis,对其的核⼼数据结构,部署架构,⾼并发问题解决⽅案有⼀定的积累
10、熟悉常⽤设计模式,并运⽤于实践⼯作中
11、了解ElasticSearch,对其核⼼的原理有⼀定的了解
12、了解K8s,Jekins,GitLab
13、了解VUE,GO
14、⽬前有正在利⽤闲暇时间做互游游戏,开发、运维、运营、推销等

本人著作git项目:https://gitee.com/zhouzhz/star-jersey-platform,有兴趣的可以私聊博主一起编写,或者给颗star
领域:对支付(FMS,FUND,PAY),订单(OMS),出行行业等有相关的开发领域
如果此文还不错的话,还请关注、点赞、收藏三连支持一下博主~

文章目录

  • 1、整体Aware接口图谱
  • 2、Aware在工作中如何使用?
    • 2.1、ApplicationContextAware(常用)
      • 2.1.1、使用例子
    • 2.2、BeanClassLoadAware(常用)
      • 2.2.1、使用例子
    • 2.3、ApplicationEventPublisherAware(常用)
      • 2.3.1、使用例子
        • 2.3.1.1、pojo
        • 2.3.1.2、controller
        • 2.3.1.3、service
        • 2.3.1.4、listener
        • 2.3.1.5、event
        • 2.3.1.6、执行过程
      • 2.3.2、扩展
        • 2.3.2.1、@TransactionalEventListener 监听器
        • 2.3.2.2、可以在监听器中重新开一个事务
    • 2.4、LoadTimeWeaverAware
      • 2.4.1、使用例子
    • 2.5、MessageSourceAware(常用)
      • 2.5.1、使用例子
    • 2.6、ImportAware
      • 2.6.1、使用例子
    • 2.7、EnvironmemtAware(常用)
      • 2.7.1、研发背景
      • 2.7.2、源码介绍以及使用方法
      • 2.7.3、作用
      • 2.7.4、使用方式代码示例
      • 2.7.5、总结
    • 2.8、BeanFoctoryAware(常用)
      • 2.8.1、使用例子
    • 2.9、BeanNameAware(常用)
      • 2.9.1、使用例子
    • 2.10、EmbeddedValueResolverAware(常用)
      • 2.10.1、使用例子
    • 2.11、ResourceLoaderAware(常用)
      • 2.11.1、在springboot中使用示例
  • 3、Aware接口源码
  • 参考

前面的BeanPostProcessor章节中,我们是不是讲了XXXAware接口,是不是很好奇他们各自有什么用呢,并且各自在底层中Spring是怎么实现的呢?下面让我来一一为大家讲解。

1、整体Aware接口图谱

这个图上的基本都是Aware接口的常用实现类,下面让我来给大家一个一个的介绍
【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第1张图片

2、Aware在工作中如何使用?

2.1、ApplicationContextAware(常用)

  • 获取容器本身ApplicationContext对象,可以在bean中得到bean所在的应用上下文
  • 一般用于获取ApplicationContext对象,大家可以看一下里面的方法,其源码如下:
    【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第2张图片
    他能做的事情,方法汇总
    【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第3张图片
    【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第4张图片

2.1.1、使用例子

package com.zhz.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @description: Spring应用上下文工具类
 * @motto: 代码源于生活,高于生活艺术
 * @author: zhouhengzhe
 * @date: 2022/12/8 18:58
 * @since 1.0
 **/
@Component
public class SpringApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

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

    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        return applicationContext.getBean(clazz);
    }

    private static void checkApplicationContext() {
        if (Objects.isNull(applicationContext)) {
            throw new RuntimeException("未注入ApplicationContext,请注入");
        }
    }
}

假设我们有一个BookService类需要用到BookDao类,如下

package com.zhz.service;

import com.zhz.dao.BookDao;
import com.zhz.utils.SpringApplicationContextHolder;
import org.springframework.stereotype.Service;

/**
 * @author zhouhengzhe
 * @description: todo
 * @date 2022/11/4 10:56
 * @since v1
 */
@Service
public class BookService {
    public void sout(){
        BookDao bean = SpringApplicationContextHolder.getBean(BookDao.class);
        System.out.println(bean);
    }
}

接着我们运行一下测试类

   @Test
    public void test2(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        BookService bean = applicationContext.getBean(BookService.class);
        System.out.println(bean);
    }

【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第5张图片

2.2、BeanClassLoadAware(常用)

  • 获取加载当前bean的类加载器
  • BeanClassLoaderAware的作用是让受管Bean本身知道它是由哪一类装载器负责装载的。

2.2.1、使用例子

代码示例来源:origin: spring-projects/spring-framework

private void invokeAwareMethods(final String beanName, final Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ClassLoader bcl = getBeanClassLoader();
      if (bcl != null) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
      }
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}

代码示例来源:origin: org.springframework/spring-beans

private void invokeAwareMethods(final String beanName, final Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ClassLoader bcl = getBeanClassLoader();
      if (bcl != null) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
      }
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}

代码示例来源:origin: spring-projects/spring-framework

/**
 * Invoke {@link BeanClassLoaderAware}, {@link BeanFactoryAware},
 * {@link EnvironmentAware}, and {@link ResourceLoaderAware} contracts
 * if implemented by the given object.
 */
public static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
    ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
  if (parserStrategyBean instanceof Aware) {
    if (parserStrategyBean instanceof BeanClassLoaderAware) {
      ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
          ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      if (classLoader != null) {
        ((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
      }
    }
    if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
      ((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
    }
    if (parserStrategyBean instanceof EnvironmentAware) {
      ((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
    }
    if (parserStrategyBean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
    }
  }
}

代码示例来源:origin: org.springframework/spring-context

/**
 * Invoke {@link BeanClassLoaderAware}, {@link BeanFactoryAware},
 * {@link EnvironmentAware}, and {@link ResourceLoaderAware} contracts
 * if implemented by the given object.
 */
public static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
    ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
  if (parserStrategyBean instanceof Aware) {
    if (parserStrategyBean instanceof BeanClassLoaderAware) {
      ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
          ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      if (classLoader != null) {
        ((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
      }
    }
    if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
      ((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
    }
    if (parserStrategyBean instanceof EnvironmentAware) {
      ((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
    }
    if (parserStrategyBean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
    }
  }
}

代码示例来源:origin: spring-projects/spring-security

@Test
public void postProcessWhenBeanClassLoaderAwareThenAwareInvoked() {
  this.spring.register(Config.class).autowire();
  BeanClassLoaderAware toPostProcess = mock(BeanClassLoaderAware.class);
  this.objectObjectPostProcessor.postProcess(toPostProcess);
  verify(toPostProcess).setBeanClassLoader(isNotNull());
}

代码示例来源:origin: spring-projects/spring-integration

@Override
public void setBeanClassLoader(ClassLoader classLoader) {
  if (this.jsonObjectMapper instanceof BeanClassLoaderAware) {
    ((BeanClassLoaderAware) this.jsonObjectMapper).setBeanClassLoader(classLoader);
  }
}

代码示例来源:origin: spring-projects/spring-framework

((BeanClassLoaderAware) pfb.getHttpInvokerRequestExecutor()).setBeanClassLoader(getClass().getClassLoader());

代码示例来源:origin: camunda/camunda-bpm-platform

private void invokeAwareMethods(final String beanName, final Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}

代码示例来源:origin: spring-projects/spring-integration

private static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
    ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
  if (parserStrategyBean instanceof Aware) {
    if (parserStrategyBean instanceof BeanClassLoaderAware) {
      ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
          ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      if (classLoader != null) {
        ((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
      }
    }
    if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
      ((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
    }
    if (parserStrategyBean instanceof EnvironmentAware) {
      ((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
    }
    if (parserStrategyBean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
    }
  }
}

代码示例来源:origin: org.springframework.integration/spring-integration-core

@Override
public void setBeanClassLoader(ClassLoader classLoader) {
  if (this.jsonObjectMapper instanceof BeanClassLoaderAware) {
    ((BeanClassLoaderAware) this.jsonObjectMapper).setBeanClassLoader(classLoader);
  }
}

代码示例来源:origin: org.apache.james/james-server-lifecycle-spring

static void setBeanClassLoader(Object importer, ClassLoader cl) {
  ((BeanClassLoaderAware) importer).setBeanClassLoader(cl);
}

代码示例来源:origin: org.eclipse.gemini.blueprint/gemini-blueprint-extensions

static void setBeanClassLoader(Object importer, ClassLoader cl) {
  ((BeanClassLoaderAware) importer).setBeanClassLoader(cl);
}

代码示例来源:origin: apache/servicemix-bundles

private void forwardBeanClassLoader(BeanClassLoaderAware target) {
  if (beanClassLoader != null) {
    target.setBeanClassLoader(beanClassLoader);
  }
}

代码示例来源:origin: org.springframework.osgi/spring-osgi-annotation

static void setBeanClassLoader(Object importer, ClassLoader cl) {
  ((BeanClassLoaderAware) importer).setBeanClassLoader(cl);
}

代码示例来源:origin: spring-projects/spring-integration

((BeanClassLoaderAware) bean).setBeanClassLoader(this.beanFactory.getBeanClassLoader()); // NOSONAR

代码示例来源:origin: apache/servicemix-bundles

private void invokeAwareMethods(final String beanName, final Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}

代码示例来源:origin: org.springframework.osgi/org.springframework.osgi.extender

public void postProcessBeanFactory(BundleContext bundleContext, ConfigurableListableBeanFactory beanFactory)
      throws BeansException, OsgiException {
    Bundle bundle = bundleContext.getBundle();
    try {
      // Try and load the annotation code using the bundle classloader
      Class annotationBppClass = bundle.loadClass(ANNOTATION_BPP_CLASS);
      // instantiate the class
      final BeanPostProcessor annotationBeanPostProcessor = (BeanPostProcessor) BeanUtils.instantiateClass(annotationBppClass);
      // everything went okay so configure the BPP and add it to the BF
      ((BeanFactoryAware) annotationBeanPostProcessor).setBeanFactory(beanFactory);
      ((BeanClassLoaderAware) annotationBeanPostProcessor).setBeanClassLoader(beanFactory.getBeanClassLoader());
      ((BundleContextAware) annotationBeanPostProcessor).setBundleContext(bundleContext);
      beanFactory.addBeanPostProcessor(annotationBeanPostProcessor);
    }
    catch (ClassNotFoundException exception) {
      log.info("Spring-DM annotation package could not be loaded from bundle ["
          + OsgiStringUtils.nullSafeNameAndSymName(bundle) + "]; annotation processing disabled...");
      if (log.isDebugEnabled())
        log.debug("Cannot load annotation injection processor", exception);
    }
  }
}

代码示例来源:origin: org.eclipse.gemini.blueprint/gemini-blueprint-extender

public void postProcessBeanFactory(BundleContext bundleContext, ConfigurableListableBeanFactory beanFactory)
      throws BeansException, OsgiException {
    Bundle bundle = bundleContext.getBundle();
    try {
      // Try and load the annotation code using the bundle classloader
      Class<?> annotationBppClass = bundle.loadClass(ANNOTATION_BPP_CLASS);
      // instantiate the class
      final BeanPostProcessor annotationBeanPostProcessor = (BeanPostProcessor) BeanUtils.instantiateClass(annotationBppClass);
      // everything went okay so configure the BPP and add it to the BF
      ((BeanFactoryAware) annotationBeanPostProcessor).setBeanFactory(beanFactory);
      ((BeanClassLoaderAware) annotationBeanPostProcessor).setBeanClassLoader(beanFactory.getBeanClassLoader());
      ((BundleContextAware) annotationBeanPostProcessor).setBundleContext(bundleContext);
      beanFactory.addBeanPostProcessor(annotationBeanPostProcessor);
    }
    catch (ClassNotFoundException exception) {
      log.info("Spring-DM annotation package could not be loaded from bundle ["
          + OsgiStringUtils.nullSafeNameAndSymName(bundle) + "]; annotation processing disabled...");
      if (log.isDebugEnabled())
        log.debug("Cannot load annotation injection processor", exception);
    }
  }
}

代码示例来源:origin: org.springframework.integration/spring-integration-core

private static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
    ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
  if (parserStrategyBean instanceof Aware) {
    if (parserStrategyBean instanceof BeanClassLoaderAware) {
      ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
          ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      if (classLoader != null) {
        ((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
      }
    }
    if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
      ((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
    }
    if (parserStrategyBean instanceof EnvironmentAware) {
      ((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
    }
    if (parserStrategyBean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
    }
  }
}

代码示例来源:origin: pl.edu.icm.synat/synat-platform-connector

@Override
protected <T> T createService(ConnectionDescriptor connectionDescriptor, Class<T> serviceInterface, String serviceId, boolean stateful) {
  final HttpInvokerProxyFactoryBean proxyFactoryBean = new HttpInvokerProxyFactoryBean();
  proxyFactoryBean.setServiceInterface(serviceInterface);
  proxyFactoryBean.setServiceUrl(connectionDescriptor.getLocation().toString());
  final HttpInvokerRequestExecutor executor;
  final HttpClient httpClient = createHttpClient();
  if (stateful) {
    executor = new SessionInvokerRequestExecutor(httpClient, serviceSecurityContext, requestConfig);
  } else {
    executor = new DefaultHttpInvokerRequestExecutor(httpClient, serviceSecurityContext, requestConfig);
  }
  if (executor instanceof BeanClassLoaderAware) {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    ((BeanClassLoaderAware) executor).setBeanClassLoader(classLoader);
  }
  proxyFactoryBean.setHttpInvokerRequestExecutor(executor);
  proxyFactoryBean.afterPropertiesSet();
  @SuppressWarnings("unchecked")
  final T service = clientInterceptorUtil.addHttpInterceptors((T) proxyFactoryBean.getObject(), connectionDescriptor);
  return service;
}

2.3、ApplicationEventPublisherAware(常用)

  • 事件发布器的接口,使用这个接口,我们自己的bean就拥有了发布事件的能力。
  • 监听器可以使核心业务与子业务进行解耦,也方便后期的业务的扩展。如新用户注册之后,发送邮件或短信,此时可以在保存用户之后,发布一个新用户的注册成功事件,通过监听该事件来实现发送邮件或短信的功能。后期新增一个对新用户进行xxx功能,此时可以新写一个监听注册成功事件的监听器,来处理新的业务逻辑,而不需要修改之前的注册逻辑。

2.3.1、使用例子

2.3.1.1、pojo

package com.zhz.bean;

import lombok.*;

/**
 * @author zhouhengzhe
 * @date 2022/12/13
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class User {
    private Integer id;
    private String name;
    private String phoneNum;
    private String email;
}

2.3.1.2、controller

@RestController
@RequestMapping("/user")
public class UserRegisterController {
    @Autowired
    private UserRegisterService userRegisterService;
    @RequestMapping("/register")
    public String register(User user) {
        //进行注册
        userRegisterService.register(user);
        return "[controller]注册用户成功!";

    }
}

2.3.1.3、service

@Service
public class UserRegisterService implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher applicationEventPublisher;

    public boolean register(User user) {

        //用户注册
        System.out.println("[service]用户["  + user + "]注册成功!");

        //消息发布
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this, user));

        return true;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;

    }
}

2.3.1.4、listener

@Component
public class EventListener implements ApplicationListener<UserRegisterEvent> {

    @Override
    public void onApplicationEvent(UserRegisterEvent event) {

        //发邮件
        System.out.println("正在发送邮件至: " + event.getUser().getEmail());

        //发短信
        System.out.println("正在发短信到: " + event.getUser().getPhoneNum());
    }
}

可以使用注解
@EventListener
使用在类上表示是监听方法(未验证)

//监听事件
@EventListener
public void listenEvent(UserRegisterEvent event) {
        //发邮件
        System.out.println("正在发送邮件至: " + event.getUser().getEmail());

        //发短信
        System.out.println("正在发短信到: " + event.getUser().getPhoneNum());
}

2.3.1.5、event

@Getter
public class UserRegisterEvent extends ApplicationEvent {
    private static final long serialVersionUID = -5481658020206295565L;
    private User user;
    //谁发布的这个事件,souce就是谁(对象)
    public UserRegisterEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
}

2.3.1.6、执行过程

  • controller层调用service中的注册方法触发监听事件,并创建这个事件类(内部可做其他操作),然后.publishEvent发布事件。监听这个事件类的监听器就会监听到这个事件,然后onApplicationEvent执行内部方法。

2.3.2、扩展

2.3.2.1、@TransactionalEventListener 监听器

  • 如果事件的发布不是在事务(@Transactional)范围内,则监听不到该事件,除非将fallbackExecution标志设置为true(@TransactionalEventListener(fallbackExecution = true));如果在事务中,可以选择在事务的哪个阶段来监听事件,默认在事务提交后监听。
修改监听事务的范围:@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)

2.3.2.2、可以在监听器中重新开一个事务

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void listenEvent1(UserRegisterEvent event) {
    divide(event);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void divide(UserRegisterEvent event) {
    //发邮件
    System.out.println("正在发送邮件至: " + event.getUser().getEmail());

//发短信
System.out.println("正在发短信到: " + event.getUser().getPhoneNum());
}
  • 以上事件都是同步,如果需要异步则需要开启异步支持,在监听器方法加上@Async 注解即可。一旦开始异步执行,方法的异常将不会抛出,只能在方法内部处理。
  • 需在方法外处理异常:https://www.baeldung.com/spring-async#enable-async-support

2.4、LoadTimeWeaverAware

  • 可获取LoadTimeWeaver实例,用于在加载时处理类定义

2.4.1、使用例子

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		//初始化所有的(非懒加载的)单实例bean
		beanFactory.preInstantiateSingletons();
	}

2.5、MessageSourceAware(常用)

  • 国际化处理相关
  • 项目启动时不同环境加载不同的配置。

2.5.1、使用例子

  • https://www.jb51.net/article/200499.htm

2.6、ImportAware

  • 用来处理自定义注解的,比如将注解里面的某些属性值赋值给其他Bean
  • ImportAware也是要配合@Import()注解一起使用

2.6.1、使用例子

  • https://blog.csdn.net/qq_38289451/article/details/122001815

2.7、EnvironmemtAware(常用)

  • 可以获取到系统的环境变量信息

2.7.1、研发背景

我們在搞新的配置中心Nacos的時候,为了获取新的配置中心的配置文件中配置的 dataId,以及配置 serverAddr、nacosGroup 等信息,所以才研究 EnvironmentAware 接口的如果写死话那岂不是太不像话了,那就太多的魔法值了,所以我们可以通过 environmentAware 这个接口进行从配置文件中【application.properties】获取配置的配置中心的信息详情。
nacos.config.server-addr=IP地址
nacos.config.data-id=api.properties
nacos.config.group=DEFAULT_GROUP
nacos.config.namespace=public
nacos.config.username=nacos
nacos.config.password=nacos
nacos.config.auto-refresh=true
nacos.config.type=properties
nacos.config.bootstrap.enable=true
nacos.config.bootstrap.log-enable=true

2.7.2、源码介绍以及使用方法

  • 其实说白了就是哪个接口需要获取配置,那么那个接口就需要进行实现该接口 EnvironmentAware并实现里面的 setEnvironment方法
/**
   其实说白了就是哪个接口需要获取配置,那么那个接口就需要进行实现该接口并实现里面的set方法
*/
public interface EnvironmentAware extends Aware {
 
    void setEnvironment(Environment environment);
 
}

2.7.3、作用

  • 所有注册到 Spring容器内的 bean,只要该bean 实现了 EnvironmentAware接口,并且进行重写了setEnvironment方法的情况下,那么在工程启动时就可以获取得 application.properties 的配置文件配置的属性值,这样就不用我们将魔法值写到代码里面了

2.7.4、使用方式代码示例

  • 通过 NacosController 实现了 EnvironmentAware 这个接口,并且实现了 setEnvironment 方法,之后通过 environment 这个对象进行配置信息获取
@RestController
@RequestMapping("/nacos")
public class NacosController implements EnvironmentAware {

    private final static String NACOS_DATA_ID = "nacos.config.data-id";
    private final static String NACOS_GROUP = "nacos.config.group";

    private static String dataId = "";
    private static String group = "";

    @NacosInjected
    private ConfigService configService;

    @Autowired
    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
    // 通过 environment 获取配置信息
    @PostConstruct
    private void init() {
        dataId = environment.getProperty(NACOS_DATA_ID);
        group = environment.getProperty(NACOS_GROUP);
    }

    /**
     * 发布配置
     * @return
     */
    @RequestMapping(value = "/publishConfig",method = RequestMethod.GET)
    public boolean publishConfig() {
        boolean res = false;
        try {
            res = configService.publishConfig(dataId, group, "发布配置");
        } catch (NacosException e) {
            e.printStackTrace();
        }
        System.out.println(res);
        return res;
    }
}

2.7.5、总结

  • 哪个类需要获取配置信息那么该类就需要进行该接口 environmentAware 的实现
  • 实现 environmentAware 这个接口所提供的方法 setEnvironment()
  • 通过 environment 进行配置信息获取

2.8、BeanFoctoryAware(常用)

  • 负责生产和管理Bean的工厂
  • 简单来说就是可以获取到BeanFactory,然后可以针对BeanFactory工厂做出自己想要的,比如获取Bean,判断Bean是否在容器等等。

2.8.1、使用例子

  • https://blog.csdn.net/FBB360JAVA/article/details/121272551

2.9、BeanNameAware(常用)

  • 组件在IOC容器里面的名字
  • BeanNameAware接口的作用就是让实现这个接口的Bean知道自己在Spring IOC容器里的名字

使用场景,比如一个service的实现类中,有两个接口的实现类,但是A需要调用B,涉及到事务,可能就会失效,就可以采用自己类调方法,就可以用这个了。

2.9.1、使用例子

@Component
public class Tiger implements BeanNameAware {

    @Override
    public void setBeanName(String name) {
        System.err.println("Bean的名字:" + name);
    }
    
}

2.10、EmbeddedValueResolverAware(常用)

  • 可以获取Spring加载properties文件的属性值

2.10.1、使用例子

@Component
public class Tiger implements EmbeddedValueResolverAware {
	 @Override
     public void setEmbeddedValueResolver(StringValueResolver resolver) {

        String val = resolver.resolveStringValue("当前操作系统为:${os.name},表达式(3*4)的结果:#{3*4}");
        System.err.println("解析后的字符串=》" + val);
    }

}

2.11、ResourceLoaderAware(常用)

  • 可获取Spring中配置的加载程序(ResourceLoader),用于对资源进行访问;可用于访问类,类路径或文件资源
  • Spring ResourceLoader为我们提供了一个统一的getResource()方法来通过资源路径检索外部资源。从而将资源或文件(例如文本文件、XML文件、属性文件或图像文件)加载到Spring应用程序上下文中的不同实现
  • 资源(Resource)接口
    • Resource是Spring中用于表示外部资源的通用接口。
    • Spring为Resource接口提供了以下6种实现。
      • UrlResourceClassPathResource
      • FileSystemResource
      • ServletContextResource
      • InputStreamResource
      • ByteArrayResource

【Spring【IOC】】——18、自定义组件中如何注入Spring底层的组件?_第6张图片

  • ResourceLoader
    • getResource()方法将根据资源路径决定要实例化的Resource实现。 要获取ResourceLoader的引用,请实现ResourceLoaderAware接口。
Resource banner = resourceLoader.getResource("file:c:/temp/filesystemdata.txt");
  • ApplicationContext加载资源
    • 在Spring中,所有应用程序上下文都实现ResourceLoader接口。因此,所有应用程序上下文都可用于获取资源实例。
    • 要获取ApplicationContext的引用,请实现ApplicationContextAware接口。(请参考上面的ApplicationContextAware)
Resource banner = ctx.getResource("file:/user/local/filesystemdata.txt");

2.11.1、在springboot中使用示例

package com.zhz.aware;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @author zhouhengzhe
 * @date 2022/12/16
 */
@Component
public class CustomResourceLoaderAwareTest implements ResourceLoaderAware {

    @Autowired
    private ResourceLoader resourceLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        try {
            showResourceData();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void showResourceData() throws IOException
    {
        //This line will be changed for all versions of other examples
        Resource banner = resourceLoader.getResource("classpath:spring-bean.xml");

        InputStream in = banner.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        while (true) {
            String line = reader.readLine();
            if (line == null) {
                break;
            }
            System.out.println(line);
        }
        reader.close();
    }
}

3、Aware接口源码

具体核心方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		/**
    	 * 主要是加载三大Aware:BeanNameAware->BeanClassLoaderAware->BeanFactoryAware
		 * 执行顺序:
		 * BeanNameAware
		 * BeanClassLoaderAware
		 * BeanFactoryAware
		 */
		invokeAwareMethods(beanName, bean);

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			/**
Bean的后置处理器前
			 * BeanPostProcessor处理器:
             * ApplicationContextAwareProcessor
             * BeanValidationPostProcessor
             * InitDestroyAnnotationBeanPostProcessor
             * AutowiredAnnotationBeanPostProcessor

             * 处理对应的Aware接口:
			 * EnvironmentAware
			 * EmbeddedValueResolverAware
			 * ResourceLoaderAware
			 * ApplicationEventPublisherAware
			 * MessageSourceAware
			 * ApplicationStartupAware
			 * ApplicationContextAware
			 */
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
            //初始化接口
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            //Bean的后置处理器后
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

参考

  • https://www.null123.com/article/detail-74438.html
  • https://blog.csdn.net/m0_53077601/article/details/121642591
  • https://blog.csdn.net/Frankltf/article/details/102844829
  • https://www.jb51.net/article/252355.htm

你可能感兴趣的:(#,Spring,spring,java,后端)