spring bean beanDefinition instance(scope) 的关系

本文探讨了Spring框架中Bean的生命周期与不同作用域(singleton和prototype)的管理方式。通过示例代码展示了如何定义Bean及其作用域,并讨论了在不同场景下Bean实例的创建与销毁过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原生 java class 和 object.

有了 spring 后, 在中间插了一个 bean 的概念. 一个 class  1:n bean , bean 1:n object (prototype) bean 1:1 object (singoton)

其中 一个 bean 有对应的BeanDefinition,里面含 id,scope 等信息.

参考:

    1.  Bean Definition从加载、解析、处理、注册到BeanFactory的过程。

    2.  spring 的生命周期

   2. 从线上问题谈spring生命周期类lifeCycle类和bean的生命周期

   3.详解Spring事件驱动模型        事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:


    2.  Spring动态创建bean

    3.   spring bean 的生命周期.

    其他类似 BeanDefinition到Bean [没有和 spring beanFactory 的生命周期和消息结合]

       

http://blog.youkuaiyun.com/fei33423/article/details/52331435

    4.Spring中scope singleton 和 prototype详解

    4. spring mvc 的生命周期

     5. 对比阅读,dubbo 的线程池,和异常处理. 事件模式.

附件,单测证明上诉实体关系:

1.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/simple-test-spring.xml" })
@TransactionConfiguration(transactionManager = "tradeTransactionManager", defaultRollback = false)

@Service
public class SimpleSpringTest implements ApplicationListener<ContextClosedEvent> {

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        System.out.println(" SimpleSpringTest closed");
    }

    @Test
    public void testThreadPoolShutDownAndBeanScope() throws InterruptedException {

        SimpleSpringTest bean = ApplicationContextUtil.getBean(SimpleSpringTest.class);
        bean.execute();
        Thread.sleep(1000 * 60 * 3);
    }

    public void execute() {
        final ApplicationContext applicationContext = ApplicationContextUtil.getApplicationContext();
        PrototypeScopeBean bean = (PrototypeScopeBean) applicationContext.getBean("PrototypeScopeBeanAnnotationName");
        bean.submit();

        PrototypeScopeBean bean2 = (PrototypeScopeBean) applicationContext.getBean("PrototypeScopeBeanAnnotationName");
        bean2.submit();
        System.out.println("12");
         ApplicationContextUtil.getApplicationContext().getBean(SingletonScopeBean.class); 
// ③ 会抛错,org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
//No qualifying bean of type [com.test.SingletonScopeBean] is defined: 
// expected single matching bean but found 3: SingtonScopeBeanAnnotationName,SingtonScopeBeanXmlInit2,SingtonScopeBeanXmlInit3



    }

}
2.
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Scope;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;

/**
 */
@Service("SingtonScopeBeanAnnotationName")
@Scope()
public class SingletonScopeBean implements ApplicationListener<ContextClosedEvent> {
    static AtomicInteger count = new AtomicInteger();

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        System.out.println("SingletonScopeBean closed" + count.incrementAndGet());
    }

    public void print() {
        System.out.println(" print " + count.get());
    }
}

spring 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <bean id="tradeApplicationContext" class="com.ApplicationContextUtil"></bean>
    <tx:annotation-driven/>
    <context:component-scan base-package="com.test.unmock.test"/>
    <context:annotation-config/>
    <bean id="PrototypeScopeBeanXmlInit1" name="PrototypeScopeBean1_name"
          class="com.test.PrototypeScopeBean" scope="prototype"></bean>

    <bean id="PrototypeScopeBeanXmlInit2" name="PrototypeScopeBean2_name"
          class="com.test.PrototypeScopeBean" scope="prototype"></bean>
    <bean id="SingtonScopeBeanXmlInit2" name="SingtonScopeBeanName2"
          class="com.test.SingletonScopeBean"></bean>
    <bean id="SingtonScopeBeanXmlInit3" name="SingtonScopeBeanName3"
          class="com.SingletonScopeBean"></bean>

</beans>



### 手动创建和配置代理对象 BeanSpring 中,可以通过编程方式手动创建并注册代理对象作为 Bean 到应用上下文中。这种方式允许更灵活地控制 Bean 的生命周期及其行为。 对于动态创建的代理对象 bean 并将其注入到 spring 容器中的场景,通常涉及以下几个方面的工作[^1]: #### 使用 `ProxyFactory` 创建代理对象 通过使用 Spring AOP 提供的 `ProxyFactory` 类来构建目标类或接口的代理实例。这使得可以在不修改原始业务逻辑的前提下增强其功能。 ```java import org.springframework.aop.framework.ProxyFactory; // 假设有一个名为 MyServiceInterface 的接口以及它的实现类 MyServiceImpl public class DynamicProxyExample { public Object createDynamicProxy() { ProxyFactory proxyFactory = new ProxyFactory(); // 设置要被代理的目标对象 proxyFactory.setTarget(new MyServiceImpl()); // 添加通知/拦截器 proxyFactory.addAdvice((MethodInterceptor) invocation -> { System.out.println("Before method call"); try { return invocation.proceed(); // 调用实际的方法执行 } finally { System.out.println("After method call"); } }); // 返回生成的代理对象 return proxyFactory.getProxy(); } } ``` #### 将代理对象注册为 Spring 上下文中的 Bean 一旦有了代理对象,则可通过获取当前应用程序上下文并将此代理对象作为一个新的单例 Bean 注册进去。这里展示了如何利用 `ConfigurableApplicationContext` 接口完成这一操作。 ```java import org.springframework.context.ConfigurableApplicationContext; public void registerAsSpringBean(ConfigurableApplicationContext context, String beanName, Object proxyInstance){ DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)context.getBeanFactory(); // 如果已经存在同名bean则先销毁它 if(context.containsBean(beanName)){ Object existingBean = context.getBean(beanName); if(existingBean != null && existingBean instanceof DisposableBean){ ((DisposableBean)existingBean).destroy(); } defaultListableBeanFactory.removeBeanDefinition(beanName); } // 注册新bean定义 RootBeanDefinition beanDefinition = new RootBeanDefinition(Advised.class); beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); beanDefinition.setPropertyValues(new MutablePropertyValues().addPropertyValue("targetSource",proxyInstance)); defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition); // 获取刚刚注册的新bean Object registeredBean = context.getBean(beanName); } ``` 上述方法适用于希望绕过常规 XML 或 Java 配置文件而直接以程序化的方式向容器内引入特定于运行时条件下的组件的情况。不过需要注意的是,在大多数情况下推荐采用声明式的依赖注入机制而非手工编码的方式来管理 beans 和它们之间的关系,因为后者容易出错而且维护成本较高[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值