Spring进阶(一)SpringBoot替换上下文中的Bean_springboot替换bean

总结

在清楚了各个大厂的面试重点之后,就能很好的提高你刷题以及面试准备的效率,接下来小编也为大家准备了最新的互联网大厂资料。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

这种对代码的侵入性大,需要业务方配合,再说了这样做需要业务代码人员配合

二、在系统启动时直接替换

使用SpringBoot的启动事件监听机制,通过修改注册的Bean,这样业务方可以无感知的实用

实现方式

这里简化了实现的业务,提供一个简单demo,在方法执行前执行一段代码(不是通过判断参数是否时BasicBean来做了)

思路

在这里插入图片描述

  • 监听器创建
    通过实现接口ApplicationListener来创建监听器
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;

import java.util.Map;

public class DemoApplicationListener implements ApplicationListener<ApplicationEvent>, Ordered {

    /\*\*
 \* The default order for the LoggingApplicationListener.
 \*/
    public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 20;

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            System.out.println("==========ContextRefreshedEvent==========");
            //处理逻辑
           test((ContextRefreshedEvent)event);
        }

    }

    @Override
    public int getOrder() {
        return DEFAULT_ORDER;
    }


其中test方法就是具体的处理逻辑实现

  • 指定Bean获取
ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext)e.getApplicationContext();

Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(DemoAnnotaion.class);

DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)applicationContext.getBeanFactory();


  • 新对象创建
			Object obj = beansWithAnnotation.get(key);

            System.out.println(beansWithAnnotation.keySet());

            // 创建一个代理类
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());
            // 设置回调方法
            enhancer.setCallback(new DemoMethodInterceptor());
            
            Object o = enhancer.create();

这里动态代理使用cglib来实现

  • 替换老对象
 			// 消除原先的bean
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(key);

            beanFactory.removeBeanDefinition(key);

            beanDefinition.setBeanClassName(o.getClass().getCanonicalName());

            beanFactory.registerBeanDefinition(key, beanDefinition);

            beanFactory.registerSingleton(key, o);

  • 监听器注册
    在resources目录下创建META-INF/spring.factories
    在这里插入图片描述
    spring.factories
# Application Listeners
org.springframework.context.ApplicationListener=\
com.example.demo.frame.DemoApplicationListener

具体代码

目录结构

在这里插入图片描述

DemoAnnotaion
import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DemoAnnotaion {
    String[] value();
}

DemoApplicationListener
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;

import java.util.Map;

public class DemoApplicationListener implements ApplicationListener<ApplicationEvent>, Ordered {

    /\*\*
 \* The default order for the LoggingApplicationListener.
 \*/
    public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 20;

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            System.out.println("==========ContextRefreshedEvent==========");
           test((ContextRefreshedEvent)event);
        }

    }

    @Override
    public int getOrder() {
        return DEFAULT_ORDER;
    }

    private void test(ContextRefreshedEvent e){
        ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext)e.getApplicationContext();

        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(DemoAnnotaion.class);

        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)applicationContext.getBeanFactory();

        for(String key : beansWithAnnotation.keySet()) {

            Object obj = beansWithAnnotation.get(key);

            System.out.println(beansWithAnnotation.keySet());

            // 创建一个代理类
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());
            // 设置回调方法
            enhancer.setCallback(new DemoMethodInterceptor());

            Object o = enhancer.create();

            // 消除原先的bean
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(key);

            beanFactory.removeBeanDefinition(key);

            beanDefinition.setBeanClassName(o.getClass().getCanonicalName());

            beanFactory.registerBeanDefinition(key, beanDefinition);

            beanFactory.registerSingleton(key, o);
        }
    }
}

DemoMethodInterceptor
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;


public class DemoMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("\*\*\*\*\*\*cglib======");
        Object result = methodProxy.invokeSuper(o, args);
        return result;
    }
}

TestService
import org.springframework.stereotype.Component;

@Component
@DemoAnnotaion("save")
public class TestService {

    public void test(){
        System.out.println("test");
    }



### 最后

现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**

![image](https://img-blog.csdnimg.cn/img_convert/6363fc7fd2bbab1ab62e1c3212a5c40a.webp?x-oss-process=image/format,png)

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

inux、Tomcat、ZooKeeper、Netty等等**

[外链图片转存中...(img-3NlJgcR3-1715471274575)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好!对于您的问题,您可以使用Spring Framework提供的BeanDefinitionRegistry接口行动态替换Spring Bean。具体步骤如下: 1. 创建一个新的Bean定义,代替原始的Bean定义。 2. 使用BeanDefinitionRegistry接口的registerBeanDefinition()方法注册新的Bean定义。 3. 在需要使用新的Bean的地方,通过ApplicationContext获取新的Bean实例。 下面是一个示例代码: ``` @Configuration public class AppConfig { @Bean("myService") public MyService getMyService() { return new MyServiceImpl(); } } @Component public class BeanReplacer { @Autowired private ConfigurableApplicationContext applicationContext; public boolean replaceBeanDefinition(String beanName, Object beanInstance) { if (!applicationContext.containsBean(beanName)) { return false; } BeanDefinitionRegistry factory = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory(); GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(beanInstance.getClass()); definition.setInstanceSupplier(() -> beanInstance); factory.registerBeanDefinition(beanName, definition); return true; } } public class Main { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class, args); BeanReplacer replacer = context.getBean(BeanReplacer.class); MyService myService = replacer.replaceBeanDefinition("myService", new MyServiceNewImpl()) ? context.getBean(MyService.class) : context.getBean("myService", MyService.class); System.out.println(myService.getServiceName()); } } ``` 在这个例子,我们从ApplicationContext获取的MyService的实例,在执行replaceBeanDefinition()替换掉原来的Bean定义。最后重新获取MyService实例并输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值