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

news2025/1/10 11:32:01

在这里插入图片描述

📫作者简介: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接口的常用实现类,下面让我来给大家一个一个的介绍
在这里插入图片描述

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

2.1、ApplicationContextAware(常用)

  • 获取容器本身ApplicationContext对象,可以在bean中得到bean所在的应用上下文
  • 一般用于获取ApplicationContext对象,大家可以看一下里面的方法,其源码如下:
    在这里插入图片描述
    他能做的事情,方法汇总
    在这里插入图片描述
    在这里插入图片描述

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);
    }

在这里插入图片描述

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

在这里插入图片描述

  • 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/118493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode283.移动0

思路1 分析 在i位置遇到0&#xff0c;把后面的元素向前移动覆盖&#xff0c;然后把最后一个位置赋值为0即可 注意问题&#xff1a; 可能 i 一个位置 移动一次之后还是0&#xff0c;需要循环 有可能 i 位置的0 是因为 已经所有的0都到后面了 ​ 所以需要用count记录0的个数&am…

2022年区块链安全领域8成以上损失集中在DeFi和跨链桥

近期&#xff0c;欧科云链研究院上线《2022年全球区块链生态安全态势报告》&#xff0c;报告指出2022年区块链安全领域8成以上损失集中在DeFi和跨链桥&#xff0c;钓鱼攻击是最常见攻击手法。主要结论 2022年前11个月&#xff0c;OKLink共监测到区块链生态相关安全事件275起&a…

整理leetcode中”最长...“

1.最长公共子序列&#xff08;动态规划&#xff09;剑指offer95 输入&#xff1a;text1 “abcde”, text2 “ace” 输出&#xff1a;3 解释&#xff1a;最长公共子序列是 “ace” &#xff0c;它的长度为 3 。 Q1&#xff1a;为什么想到二维dp&#xff1f; A1&#xff1a;因…

JDBC第二章 (JDBC API详解)

目录 一、下载驱动包 二、加载与注册驱动 1、使用driverManager类 2、方式&#xff1a; 3、补充&#xff1a; 三、建立连接 1、URL 2.建立连接的方式 3.事务管理 4.获取Statement语句 1、普通版本 2、防止SQL注入版本 3、获取存储过程 四、Statement 1、概述 2…

数图互通高校房产管理——房屋模拟分配建设

数图互通房产管理系统在这方面做得比较全面&#xff1b; 1、 房屋模拟分配建设方案 实现对学校房屋分配进行情景模拟&#xff0c;在特定房屋类型、数量、使用面积等情况下&#xff0c;建立多个模拟分配方案&#xff0c;并对每个模拟分配方案生成明细清单。 1.1 房屋模拟分配清…

石墨烯太阳能供暖远程监控

石墨烯太阳能供暖系统是指采用全新一代石墨烯碳纤维电热膜为发热体&#xff0c;直接将电能转换为热能的供暖系统。再搭配太阳能光伏发电系统给石墨烯供暖系统供电&#xff0c;更加节能有效地解决用户用电问题。但目前这种供暖方式也存在诸多问题&#xff0c;如供暖温度得不到控…

深度学习交通标志识别项目

主要内容 在本文中&#xff0c;使用Python编程语言和库Keras和OpenCV建立CNN模型&#xff0c;成功地对交通标志分类器进行分类&#xff0c;准确率达96%。开发了一款交通标志识别应用程序&#xff0c;该应用程序具有图片识别和网络摄像头实时识别两种工作方式。 写作目的 近年…

jenkins 升级遇到问题总结

当我在使用jenkins的时候,避免不了下载很多插件,因为jenkins本身不提供很多功能,大部分的功能都是依赖插件来完成的,这也使jenkins更具有扩展性,但是,我在安装完成后打开插件列表居然是这样的。。。 或者插件列表打开的正常,但是安装某个插件时报这样的错误。。。 看标…

c++算法基础必刷题目——尺取法

文章目录尺取法1、字符串2、丢手绢尺取法 尺取法通常也叫滑动窗口法&#xff0c;顾名思义&#xff0c;像尺子一样取一段&#xff0c;借用挑战书上面的话说&#xff0c;尺取法通常是对数组保存一对下标&#xff0c;即所选取的区间的左右端点&#xff0c;然后根据实际情况不断地推…

Html网页和C++ App通信 - qwebchannel

Qt5 引入了 Qt WebChannel 的概念。这是为了在不能影响各端代码执行的前提下实现 Qt 端于 client 端的无缝 双向 通信。 QWebChannel 提供了在 C应用和 前端&#xff08;HTML/JS&#xff09;之间点对点的通信能力。通过向 前端的 QWebChannel 发布 QObject 的 派生对象&#xf…

开源版支持工作台展示,新增超级管理员用户组,MeterSphere开源持续测试平台v2.5.0发布

2022年12月27日&#xff0c;MeterSphere一站式开源持续测试平台正式发布v2.5.0版本。 在这一版本中&#xff0c;MeterSphere在工作台模块进行了UX交互升级&#xff0c;并将工作台模块由X-Pack增强功能开放为开源版功能。 在测试跟踪模块中&#xff0c;关联测试用例支持关联UI…

(四)RequestResponse

一、Request 和 Response 的概述 Request是请求对象&#xff0c;Response是响应对象。request&#xff1a;获取请求数据 &#xff08;1&#xff09;浏览器会发送HTTP请求到后台服务器 [Tomcat] &#xff08;2&#xff09;HTTP的请求中会包含很多请求数据[请求行请求头请求体] &…

26位前谷歌AI专家出走创业

细数近几年来高科技对现代社会的影响&#xff0c;人工智能&#xff08;AI&#xff09;无疑是排在前列。AI已经对人类社会行为、健康、教育和娱乐的方方面面都产生了巨大冲击。作为高科技的头部企业&#xff0c;谷歌的AI团队可能是AI行业最有影响的团队之一&#xff0c;他们的一…

第十三讲:MSTP技术应用

学校因为教师的人数越来越多&#xff0c;部门逐渐也增多&#xff0c;各部门之间都已经采用了vlan技术&#xff0c;但为了实现公司的稳定性和消除内部网络的环路&#xff0c;管理员小赵配合飞越公司去实现学校内部网络时刻不间断&#xff0c;来保证公司网络的运行。 为了解决校园…

【Lilishop商城】No4-3.业务逻辑的代码开发,涉及到:会员B端第三方登录的开发-微信小程序登录接口开发

仅涉及后端&#xff0c;全部目录看顶部专栏&#xff0c;代码、文档、接口路径在&#xff1a; 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇会结合业务介绍重点设计逻辑&#xff0c;其中重点包括接口类、业务类&#xff0c;具体的结合源代码…

工厂明火烟雾视频监控识别 烟火自动识别预警 yolo

工厂明火烟雾视频监控识别 烟火自动识别预警通过pythonyolo网络深度学习模型可以自动识别监控区域内的烟火&#xff0c;如pythonyolo网络深度学习模型发现火焰烟火可以立即抓拍告警。Python是一种由Guido van Rossum开发的通用编程语言&#xff0c;它很快就变得非常流行&#x…

Flink系列-2、Flink架构体系

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 大数据系列文章目录 官方网址&#xff1a;https://flink.apache.org/ 学习资料&#xff1a;https://flink-learning.org.cn/ 目录Flink中的重要…

[ web基础知识点 ] 解决端口被占用的问题(关闭连接)(杀死进程)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

什么是文件描述符

Linux内核在各种不同的文件系统格式之上做了一个抽象层&#xff0c;使得文件、目录、读写访问等概念成为抽象层的概念&#xff0c;因此各种文件系统看起来用起来都一样&#xff0c;这个抽象层称为虚拟文件系统(VFS&#xff0c;Virtual Filesystem)。 内核数据结构 Linux内核的V…

【endnote学习】解决为什么文献引用后出现年/月/日格式(endnote对其他类型引用文件的不兼容导致)

为什么文献引用后出现年/月/日格式问题描述问题解决问题描述 在一次文献引用中发现&#xff0c;引用后的文献格式里面多了年/月/日格式&#xff0c;比如选择AIChE格式时&#xff0c;出现&#xff1a; Liu P, Nrskov JK. Kinetics of the Anode Processes in PEM Fuel Cells …