Spring的Bean和Spring容器

几种定义Bean的方式(声明式)

  1. Bean标签取生成一个Bean

    在java中

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    //通过xml文件所指定的类的构造方法获取bean
    

    在spring.xml文件中

    <bean id="user" class="com.datum.User"/>
    
  2. @Component

    给某个类上加上@Component,再在配置类Config.java上写@ComponentScan(“包地址”)或者在spring.xml中写入一个标签<context:component-scan base-package=“com.datum”/>

    在将配置类传入Context,同样能通过getBean方法拿到对象

  3. @Bean

    方法名字为容器获取bean的名“user”

    性能要比xml要高点(解析xml文件过程)

    @Bean方式要简洁灵活点

    public class Config {
        @Bean
        public User user() {//方法名字为容器获取bean的名“user”
            return new User();
        }
    }
    
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
            annotationConfigApplicationContext.register(Config.class);
            annotationConfigApplicationContext.refresh();
            User user1 = annotationConfigApplicationContext.getBean("user", User.class);
    

    通过AnnotationConfigApplicationContext来获取一个写上注解的Bean

JavaBean SpringBean 对象之间的区别

Bean肯定是对象。

JavaBean 成员是私有的,但是要提供针对该成员的get,set方法

SpringBean 凡是由Spring生产管理的Bean都叫SpringBean

BeanDefinition(编程式定义bean,是声明式的核心)

编程式定义一个Bean

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
annotationConfigApplicationContext.registerBeanDefinition("user", beanDefinition);
annotationConfigApplicationContext.refresh();
User user = annotationConfigApplicationContext.getBean("user", User.class);
System.out.println(user);

首先获取一个context,然后通过beanDefinition设置一个BeanClass,并且注册道context,同样可以获得一个bean

FactoryBean

继承FactoryBean接口

public class DatumFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Person();
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

可以通过BeanDefinition来注册一个bean

AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition1.setBeanClass(DatumFactoryBean.class);
annotationConfigApplicationContext.registerBeanDefinition("datum", beanDefinition1);
Person datum = annotationConfigApplicationContext.getBean("datum", Person.class);
DatumFactoryBean bean = annotationConfigApplicationContext.getBean("&datum", DatumFactoryBean.class);
System.out.println(datum);
System.out.println(bean);

注意 一个FactoryBean注册会将会产生两个Bean,一个是FactoryBean本身,一个是实现FactoryBean的getObject方法的返回对象。

"datum"对应Person.class "&datum"对应DatumFactoryBean.class

如何注册一个Bean

通过@Component注册bean则需要一个@ComponentScan的class或者xml配置

通过registerBean只需要类就可以了

通过书写xml标签

通过在类上加上@component标签,在通过一个配置类Config加上@ComponentScan(“包地址”),再去context中调用context.register(Config.class)。

通过直接调用context.registerBean(User.class)方法直接注册一个Bean,后续再调用,默认调用名为首字母小写即"user"。

通过context.registerBean()传入一个Supplier

context.registerBean(User.class, new Supplier<User>() {
    @Override
    public User get() {
        User user = new User();
        user.setName("hello");
        return user;
    }
});
User user = context.getBean("user", User.class);
System.out.println(user.getName());

这个方法也可以注册一个bean

Spring容器到底是什么

<bean id="user" class="com.datum.User"/>

<bean id="user1" class="com.datum.User" scope="prototype"/>

scope::prototype原型

scope::singleton单例(spring默认是单例)

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
System.out.println(context.getBean("user", User.class));
System.out.println(context.getBean("user", User.class));
System.out.println(context.getBean("user1", User.class));
System.out.println(context.getBean("user1", User.class));

com.datum.User@51b279c9
com.datum.User@51b279c9
com.datum.User@1ad282e0
com.datum.User@7f416310

"user"打印的地址是一致的

"user1"打印的地址是不同的,对象就不同

单例池

spring启动的时候回去把非懒加载的单例池创建出来

ConcurrentHashMap singletonObject

key为String(BeanName),value为Object

BeanFactory Bean工厂

生产bean,在getBean()的时候容器中的Bean被创建(无论是不是singleton)。

是一个容器

主要储存 BeanDefinition和对象

有单例池,DefaultListableBeanFactory继承自DefaultSingletonBeanRegistry,该类有private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256)成员

但是不止是存储单例,可以通过beanDefinition设置scope为prototype(原型)

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("user", new User());
User user = beanFactory.getBean("user", User.class);
System.out.println(user);

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition("user1", beanDefinition);
User user1 = beanFactory.getBean("user1", User.class);
System.out.println(user1);

ApplicationContext

ApplicationContext容器里面的scope为singleton的对象在spring启动的时候创建,scope为prototype的对象在获取的时候创建。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver

继承了很多接口,集成了很多功能,例如EnvironmentCapable获取系统和jvm环境,MessageSource国际化,ApplicationEventPublisher事件发布,ResourcePatternResolver资源匹配,资源解析

拥有BeanFactory的功能并且超越了BeanFactory

通过context获取系统环境,和jvm环境

AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
System.out.println(applicationContext.getEnvironment().getSystemEnvironment());   System.out.println(applicationContext.getEnvironment().getSystemProperties());

ClassPathXmlApplicationContext和FileSystemXmlApplicationContext的区别

ClassPathXmlApplicationContext(“spring.xml”)代码中的spring.xml指的是classpath:目录下的spring.xml

FileSystemXmlApplicationContext(“spring.xml”)代码中的spring.xml指的是工程目录下的spring.xml

FileSystemXmlApplicationContext(“src/main/resources/spring.xml”)等同classpath:目录下的spring.xml

ClassPathXmlApplicationContext:不指绝对路径,只支持从classpath相对路径

FileSystemXmlApplicationContext:支持绝对路径,也支持工程目录相对路径

ClassPathXmlApplicationContext和AnnotationConfigApplication的区别

ClassPathXmlApplicationContext:通过传入一个xml文件,支持重复刷新,因为它继承了AbstractRefreshableConfigApplicationContext–》AbstractRefreshableApplicationContext

AnnotationConfigApplication:通过传入一个配置类的.class,不支持重复刷新,它继承自GenericApplicationContext

刷新后的效果相当与把所有bean对象销毁,重新读取spring.xml文件再重新生成bean

所有单例bean不再是之前的bean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值