在 Spring 容器初始化 Bean 时,通过反射机制处理带有自定义 注解的字段,并将其注入相应的 Spring 管理的 Bean

背景:我们之前项目用的自己研发的框架,后来又要重构,但是有些功能还依赖于之前的框架,万不得已的情况下,我就把之前的框架当成三方的依赖给引入,引入以后就发现,很多类上用了@Inject这个注解,再一看包名竟然是自定义的,这几个类就是无法注入到spring中,用了好多种方法,使用的时候永远null,

话不多说,直接上代码

java 复制代码
package com.pj.atomarrowSy.processor;

import net.atomarrow.annotation.Inject;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
 * 处理器的作用:
 * 在 Spring 容器初始化 Bean 时,
 * 通过反射机制处理带有自定义注解 @Inject 的字段,
 * 并将这些字段注入相应的 Spring 管理的 Bean。
 * implements BeanPostProcessor:实现 BeanPostProcessor 接口,允许在 Bean 初始化前后进行自定义处理
 * implements ApplicationContextAware:实现 ApplicationContextAware 接口,使得该类可以获取到当前的 ApplicationContext,从而能够访问 Spring 容器中的其他 Bean。
 */
@Component
public class CustomInjectAnnotationBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware{
    private ApplicationContext applicationContext;

    //在 Bean 初始化之前调用的方法。
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 遍历 Bean 中的所有字段
//        System.out.println("Processing bean: " + beanName);
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Inject.class)) { //检查字段是否有 @Inject 注解
                System.out.println("Found @Inject annotation on field: " + field.getName() + " in class: " + bean.getClass().getName());
                try {
                    field.setAccessible(true);// 设置字段可访问
                    Object fieldValue = applicationContext.getBean(field.getType()); // 从 Spring 容器中获取相应类型的 Bean
                    if (fieldValue == null) {
                        System.err.println("Bean not found in context for type: " + field.getType().getName() + " in class: " + bean.getClass().getName());
                    } else {
                        field.set(bean, fieldValue);// 将获取到的 Bean 注入到字段中
                        System.out.println("Injected field: " + field.getName() + " with value: " + fieldValue + " in class: " + bean.getClass().getName());
                    }
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Failed to inject field: " + field.getName() + " in class: " + bean.getClass().getName(), e);
                }
            }
        }
        return bean; // 返回处理后的 Bean
    }
    //在 Bean 初始化之后调用的方法。这里没有做任何额外处理,直接返回 Bean。
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 这里不需要做额外的处理
        return bean;
    }
    //实现 ApplicationContextAware 接口的方法,
    // 用于设置 ApplicationContext,使 CustomInjectAnnotationBeanPostProcessor 能够访问 Spring 容器中的 Bean。
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }





}
相关推荐
heartbeat..15 分钟前
Redis 常用命令全解析:基础、进阶与场景化实战
java·数据库·redis·缓存
数据知道21 分钟前
PostgreSQL 实战:一文掌握如何优雅的进行递归查询?
大数据·数据库·postgresql
Hello.Reader25 分钟前
Flink 2.2 Docker 部署Session / Application / SQL Client 一把梭(含 Compose、插件、连接器与踩坑点)
sql·docker·flink
陌上丨25 分钟前
MySQL8.0高可用集群架构实战
数据库·mysql·架构
重生之绝世牛码36 分钟前
Linux软件安装 —— ClickHouse单节点安装(rpm安装、tar安装两种安装方式)
大数据·linux·运维·数据库·clickhouse·软件安装·clickhouse单节点
一只自律的鸡1 小时前
【MySQL】第十一章 存储过程和存储函数
数据库·mysql
翔云1234561 小时前
MySQL 中的 utf8 vs utf8mb4 区别
数据库·mysql
数据知道1 小时前
PostgreSQL 实战:索引的设计原则详解
数据库·postgresql
老毛肚1 小时前
Spring 6.0基于JDB手写定制自己的ROM框架
java·数据库·spring
CodeBlossom1 小时前
MySQL进阶 索引
数据库·mysql