1、包扫描+组件标注注解
使用到的注解如下,主要针对自己写的类
- @Controller
- @Service
- @Repository
- @Component
- @ComponentScan
参考 spring注解开发:ComponentScan组件扫描
2、使用bean注解
主要使用场景:导入第三方包里面的组件,使用到的注解:
- @Bean
参考:spring注解开发:Configuration&Bean
3、使用@Import注解
- 使用方式:@Import(要导入到容器中的组件);容器中就会自动注册这个组件
- bean的id默认是全类名
- 示例:@Import(value = {Person.class})
实战
1、新建一个maven工程,添加如下依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
2、新建一个实体 Person
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 +
'}';
}
}
3、新建一个配置类(重点)
package com.yefengyu.annotation.config; import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*; @Configuration
@Import(Person.class)
public class MainConfig
{
}
4、测试代码
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");
}
4、使用ImportSelector
ImportSelector和Import一起使用:首先编写一个类实现ImportSelector接口MyImportSelector,然后将MyImportSelector添加到Import中,那么MyImportSelector自定义逻辑返回需要导入的组件就会被加入到容器中。
利用上面第三节的代码,我们重新添加一个类,这个类什么都没有,现在我们尝试着使用ImportSelector方式将其注册到容器中。
package com.yefengyu.annotation.bean; public class Car
{
}
1、编写MyImportSelector实现ImportSelector接口,重写selectImports方法,返回的数组中每个字符串就是要导入到容器的组件的全类名。
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"};
}
}
2、修改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
{
}
3、测试,同样使用上面的测试代码,可以看出打印结果为:
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
4、针对于public String[] selectImports(AnnotationMetadata annotationMetadata)方法中的参数AnnotationMetadata有很多信息可以帮助筛选要注册的组件。
5、使用ImportBeanDefinitionRegistrar
和使用ImportSelector方式一样,定义一个类实现ImportBeanDefinitionRegistrar接口,重写其中的方法,手动注册组件。
1、定一个类,作为要注册的组件
package com.yefengyu.annotation.bean; public class Alarm
{
}
2、实现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 的功能很多:
3、修改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
{
}
4、测试,同样使用上面的测试代码,可以看出打印结果为:
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
6、使用FactoryBean
1、首先创建一个待加入到容器的组件
package com.yefengyu.annotation.bean; public class Event
{
}
2、创建一个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;
}
}
3、修改配置类,注意下面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();
}
}
4、修改测试代码如下:
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());
}
}
5、结果如下:
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");