Spring定义Bean的六种方式

109 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

一、xml 配置文件

这种方式在 SpringMVC 中是常用的方式,Spring 启动时会读取配置文件,并将配置文件中配置好的类加入到 IOC 容器中。

<!--spring.xml-->

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

这里我们测试使用main函数。

使用ClassPathXmlApplicationContext()读取配置并启动一个 Spring IOC 容器。调用容器的getBean方法返回需要的对象。

public class Main {

    public void getBeanOne() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }

}

二、配置类

这种方式比较类似于第一种配置文件,但是这种更效率。

创建一个配置类,配合使用@Bean注解,以成员方法的形式返回 Bean 实例。

//在配置类中返回new出来的Bean,效率比第一种高

public class ConfigBean {

    @Bean
    public User user(){
        return new User();
    }

}

使用AnnotationConfigApplicationContext()读取配置类并启动一个 Spring IOC 容器。调用容器的getBean()方法返回需要的对象。

public class Main {

    public void getBeanTwo() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigBean.class);
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }

}

三、扫描包

通过@ComponentSacn扫描包形式获取 Bean,被扫描的包下的所有带@Component注解的类都会被认为是 Bean。

@ComponentScan("com.shacoz.bean")
public class ConfigBean {

}

四、BeanDefinition 构建

编程式使用 BeanDefinition 构建 Bean,前三种方式也是基于底层 BeanDefinition 构建出来的。

这种方式更复杂,也更底层。

public class Main{

    public void main(){
        // 创建Spring容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 创建一个BeanDefinition,用来描述Bean
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(Dog.class);
        // 将bean放入Spring容器中
        applicationContext.registerBeanDefinition("dog",beanDefinition);
        // 刷新Spring容器
        applicationContext.refresh();
        // 获取Bean
        Dog dog = applicationContext.getBean("dog", Dog.class);
        System.out.println(dog);
    }

}

五、FactoryBean 构建

使用 FactoryBean 构建特殊 Bean,使用 FactoryBean,Spring 会构建两个 Bean,一个是外层类的类型,一个是返回 Bean 的类型,外层类型是通过 Bean 名字前面加&符号获取。

// 创建一个Cat对象,外层是Animal
public class Animal implements FactoryBean {

    @Override
    public Object getObject() throws Exception {
        return new Cat();   // 返回Cat对象
    }

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

}

创建容器后,外层类型作为 Bean 的类型注册到容器中,在调用getBean()方法时,默认返回getObject()返回的对象。 如果在 Bean 的名字前面加&,则可以获取到外层类型。

public class Main{

    public void getBeanFive(){
        // 创建Spring容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 创建一个BeanDefinition,用来描述Bean
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        // 构建两个Bean,一个是Animal类型的,一个Cat类型的
        beanDefinition.setBeanClass(Animal.class);
        // 将bean放入Spring容器中
        applicationContext.registerBeanDefinition("cat",beanDefinition);
        // 刷新Spring容器
        applicationContext.refresh();
        // 获取Bean,通过cat获取的是Cat类型的,&cat则获取Animal类型的
        Cat cat = applicationContext.getBean("cat", Cat.class);
        Animal cat = applicationContext.getBean("&cat", Animal.class);
        System.out.println(cat);
    }

}

FactoryBean 产生单个 Bean,在 IOC 容器的基础上给 Bean 的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂 Bean,由 Spring 管理后,生产的对象是由getObject()方法决定的。

// FactoryBean 源码

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

六、registerBean 直接注册 Bean

在构建 Bean 时使用 Supplier 初始化 Bean 的参数,当然也可以做一些逻辑操作。Supplier 可以简写到 lambda 表达式。

public class Main{
    public void getBeanSix(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 构建Supplier可以在构建Bean时初始化Bean的相关参数
        applicationContext.registerBean(Cat.class, new Supplier<Cat>() {
            @Override
            public Cat get() {
                Cat cat = new Cat();
                cat.setName("咪咪");
                return cat;
            }
        });
        // 使用Lambda表达式简写Supplier
        applicationContext.registerBean(Dog.class, () -> {
            Dog dog = new Dog();
            dog.setName("汪汪");
            return dog;
        });
        applicationContext.refresh();
        Cat cat = applicationContext.getBean("cat", Cat.class);
        Dog dog = applicationContext.getBean("dog", Dog.class);
        System.out.println(cat);
        System.out.println(dog);
    }
}

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情