spring註解開發:容器中註冊組件方式

一、包掃描+組件標註註解


使用到的註解以下,主要針對本身寫的類html

  • @Controller
  • @Service
  • @Repository
  • @Component
  • @ComponentScan

參考 spring註解開發:ComponentScan組件掃描spring

二、使用bean註解


主要使用場景:導入第三方包裏面的組件,使用到的註解:

  • @Bean
參考:spring註解開發:Configuration&Bean

三、使用@Import註解


  • 使用方式:@Import(要導入到容器中的組件);容器中就會自動註冊這個組件
  • bean的id默認是全類名
  • 示例:@Import(value = {Person.class})

實戰數組

一、新建一個maven工程,添加以下依賴maven

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

二、新建一個實體 Personide

package com.yefengyu.annotation.bean;

public class Person
{
    private String name;

    private Integer age;

    public Person()
    {
    }

    public Person(String name, Integer age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Integer getAge()
    {
        return age;
    }

    public void setAge(Integer age)
    {
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
    }
}

三、新建一個配置類(重點測試

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import(Person.class)
public class MainConfig
{
}

四、測試代碼ui

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = ctx.getBeanDefinitionNames();
    for (String name : names)
    {
        System.out.println(name);
    }
    Person person1= (Person)ctx.getBean(Person.class);
    //bean的id默認是全類名
     Person person2= (Person)ctx.getBean("com.yefengyu.annotation.bean.Person");
}

四、使用ImportSelector


ImportSelector和Import一塊兒使用:首先編寫一個類實現ImportSelector接口MyImportSelector,而後將MyImportSelector添加到Import中,那麼MyImportSelector自定義邏輯返回須要導入的組件就會被加入到容器中。this

利用上面第三節的代碼,咱們從新添加一個類,這個類什麼都沒有,如今咱們嘗試着使用ImportSelector方式將其註冊到容器中。spa

package com.yefengyu.annotation.bean;

public class Car
{
}

一、編寫MyImportSelector實現ImportSelector接口,重寫selectImports方法,返回的數組中每一個字符串就是要導入到容器的組件的全類名。code

package com.yefengyu.annotation;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

//自定義邏輯返回須要導入的組件
public class MyImportSelector implements ImportSelector
{
    //返回值就是要導入到容器的組件的全類名
     @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata)
    {
        return new String[]{"com.yefengyu.annotation.bean.Car"};
    }
}

二、修改MainConfig配置類,使用Import註解加入MyImportSelector類,注意下面紅色部分。

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class})
public class MainConfig
{
}

三、測試,一樣使用上面的測試代碼,能夠看出打印結果爲:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car

四、針對於public String[] selectImports(AnnotationMetadata annotationMetadata)方法中的參數AnnotationMetadata有不少信息能夠幫助篩選要註冊的組件。

image

五、使用ImportBeanDefinitionRegistrar


和使用ImportSelector方式同樣,定義一個類實現ImportBeanDefinitionRegistrar接口,重寫其中的方法,手動註冊組件。

一、定一個類,做爲要註冊的組件

package com.yefengyu.annotation.bean;

public class Alarm
{
}

二、實現ImportBeanDefinitionRegistrar接口,手動註冊組件

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Alarm;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
                                        BeanDefinitionRegistry beanDefinitionRegistry)
    {
        beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));
    }
}

beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));

第一個參數是組件名稱。

第二個參數是要註冊的組件的類型的定義。

AnnotationMetadata 和上一節相似。BeanDefinitionRegistry 的功能不少:

image

三、修改MainConfig配置類,使用Import註解加入MyImportBeanDefinitionRegistrar類,注意下面紅色部分。

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
}

四、測試,一樣使用上面的測試代碼,能夠看出打印結果爲:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
alarm

六、使用FactoryBean


一、首先建立一個待加入到容器的組件

package com.yefengyu.annotation.bean;

public class Event
{
}

二、建立一個Spring定義的FactoryBean

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Event;
import org.springframework.beans.factory.FactoryBean;


//建立一個Spring定義的FactoryBean
public class EventFactoryBean implements FactoryBean<Event>
{
    //返回一個Event對象,這個對象會添加到容器中
    @Override
    public Event getObject()
        throws Exception
    {
        return new Event();
    }

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

    //是單例?
    //true:這個bean是單實例,在容器中保存一份
    //false:多實例,每次獲取都會建立一個新的bean;
    @Override
    public boolean isSingleton()
    {
        return true;
    }
}

三、修改配置類,注意下面bean註解下面的代碼

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.EventFactoryBean;
import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
    @Bean
    public EventFactoryBean eventFactoryBean()
    {
        return new EventFactoryBean();
    }
}

四、修改測試代碼以下:

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Person;
import com.yefengyu.annotation.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Main
{
    public static void main(String[] args)
    {
        ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
        String[] names = ctx.getBeanDefinitionNames();
        for (String name : names)
        {
            System.out.println(name);
        }
        //測試EventFactoryBean
        Object eventFactoryBean = ctx.getBean("eventFactoryBean");
        System.out.println("bean 的類型爲:" + eventFactoryBean.getClass());

        Object factoryBean = ctx.getBean("&eventFactoryBean");
        System.out.println("bean 的類型爲:" + factoryBean.getClass());
    }
}

五、結果以下:

mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
eventFactoryBean
alarm
bean 的類型爲:class com.yefengyu.annotation.bean.Event bean 的類型爲:class com.yefengyu.annotation.EventFactoryBean

總結:

  • 默認獲取到的是工廠bean調用getObject建立的對象

    ctx.getBean("eventFactoryBean");

  • 要獲取工廠Bean自己,咱們須要給id前面加一個&

    ctx.getBean("&eventFactoryBean");

相關文章
相關標籤/搜索