(001)spring容器创建bean的两种方式

Posted 明月之诗

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(001)spring容器创建bean的两种方式相关的知识,希望对你有一定的参考价值。

简单记录一下spring容器创建、装配、管理bean

1、使用@Configuration、@Bean的注解组合创建bean

   可以用两种方法获取bean,根据类名或者创建bean的方法名,如果不指定bean的名字,默认bean的名字是该方法名。

  pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.edu.spring</groupId>
    <artifactId>spring</artifactId>
    <version>1.0.0</version>

    <name>spring</name>
    <!-- FIXME change it to the project\'s website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
    </dependencies>

</project>
View Code

  MyBean.java如下:

package com.edu.spring;

public class MyBean {

}
View Code

  MyConfig.java如下:

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    
    @Bean
    public MyBean createMyBean() {
        return new MyBean();
    }
}
View Code

  App.java如下:

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(MyBean.class));
        System.out.println(context.getBean("createMyBean"));
        context.close();
    }
}
View Code

  运行结果如下:

  指定bean的名字,可以在@bean添加name属性,如下:

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    
    @Bean(name="myBean")
    public MyBean createMyBean() {
        return new MyBean();
    }
}
View Code

   同样获取bean时,将App.java中修改为bean的name中指定的,如下:

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(MyBean.class));
        System.out.println(context.getBean("myBean"));
        context.close();
    }
}
View Code

  运行结果如下:

   上面两个运行结果可以发现,bean是单例的,使用@Scope("prototype")将单例修改为多例:

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class MyConfig {
    
    @Bean(name="myBean")
    @Scope("prototype")
    public MyBean createMyBean() {
        return new MyBean();
    }
}
View Code

  运行结果如下:

  使用@Configuration、@Bean的注解组合的变体创建bean

  Car.java

package com.edu.spring;

public class Car {

}
View Code

  CarFactory.java

package com.edu.spring;

public class CarFactory {

    public Car create(){
        return new Car();
    }
}
View Code

  MyConfig.java   spring容器装配CarFactory这个bean,创建Car这个bean的时候,形参接收的是spring容器已经创建的CarFactory这个bean

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    
    @Bean
    public CarFactory createJeepFactory(){
        return new CarFactory();
    }
    
    @Bean
    public Car createCar(CarFactory factory){
        return factory.create();
    }
}
View Code

  App.java

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(Car.class));
        context.close();
    }
}
View Code

  运行结果如下:

 2、实现FactoryBean接口创建bean

  FactoryBean有3个方法,获取对象、获取对象类型、默认不是单例,如下:

   RunnableFactoryBean.java实现FactoryBean接口如下:

package com.edu.spring;

import org.springframework.beans.factory.FactoryBean;

public class RunnableFactoryBean implements FactoryBean<Runnable> {

    @Override
    public Runnable getObject() throws Exception {
        // TODO Auto-generated method stub
        return () -> {};
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Runnable.class;
    }

    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return true;
    }

}
View Code

  配置类MyConfig.java中给RunnableFactoryBean添加Bean注解如下:

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    
    @Bean
    public RunnableFactoryBean createRunnableFactoryBean(){
        return new RunnableFactoryBean();
    }
}
View Code

  App.java如下:

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(RunnableFactoryBean.class));
        System.out.println(context.getBean(Runnable.class));
        context.close();
    }
}
View Code

  运行结果如下:

   可以看到RunnableFactoryBean与Runnable的Bean都可以获取,Runnable是用Lambda实现的,所以看起来有点怪,下面不用Lambda表达式

  Jeep.java

package com.edu.spring;

public class Jeep {

}
View Code

  RunnableFactoryBean.java

package com.edu.spring;

import org.springframework.beans.factory.FactoryBean;

public class RunnableFactoryBean implements FactoryBean<Jeep> {

    @Override
    public Jeep getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Jeep();
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Jeep.class;
    }

    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return true;
    }

}
View Code

  MyConfig.java

package com.edu.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    
    @Bean
    public RunnableFactoryBean createRunnableFactoryBean(){
        return new RunnableFactoryBean();
    }
}
View Code

  App.java 根据类获取与根据bean的名字获取是一样的

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(RunnableFactoryBean.class));
        System.out.println(context.getBean(Jeep.class));
        System.out.println(context.getBean("createRunnableFactoryBean"));
        context.close();
    }
}
View Code

  运行结果如下:

   将RunnableFactoryBean.java中改为不是单例

package com.edu.spring;

import org.springframework.beans.factory.FactoryBean;

public class RunnableFactoryBean implements FactoryBean<Jeep> {

    @Override
    public Jeep getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Jeep();
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Jeep.class;
    }

    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }

}
View Code

  App.java 两次获取的bean不一样

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(RunnableFactoryBean.class));
        System.out.println(context.getBean(Jeep.class));
        System.out.println(context.getBean("createRunnableFactoryBean"));
        context.close();
    }
}
View Code

  运行结果如下:

   从MyConfig.java中可以看到,创建的bean是RunnableFactoryBean,根据名字获取:context.getBean("createRunnableFactoryBean"))得到的却是泛型中的类的bean:com.edu.spring.Jeep@6e2c9341,这是因为RunnableFactoryBean实现了FactoryBean接口,这个接口是特殊的,如果要根据RunnableFactoryBean的名字获取bean,可以用下面方式:

  App.java 中名字前面加&

package com.edu.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean(Jeep.class));
        System.out.println(context.getBean("createRunnableFactoryBean"));
        System.out.println(context.getBean(RunnableFactoryBean.class));
        System.out.println(context.getBean("&createRunnableFactoryBean"));
        context.close();
    }
}
View Code

   运行结果如下:

 

  

 

以上是关于(001)spring容器创建bean的两种方式的主要内容,如果未能解决你的问题,请参考以下文章

Spring(十三):使用工厂方法来配置Bean的两种方式(静态工厂方法&实例工厂方法)

Spring 注入 Bean 的 7 种方式,还有谁不会?-

Spring @Configuration @Bean 给容器中注册组件

Spring 注入 Bean 的 7 种方式,还有谁不会?

Java知识点16 Spring创建IOC容器的两种方式

Spring 实例化Bean的两种方式