本篇主要记录Spring注解注入SpringIOC的方式
pom文件导入
<!-- 我使用的是4.3.12版本的Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
依赖的包有以下
向IOC容器中注入bean方式
1.@Bean注解 bean名字默认为方法名 也可指定bean名字
@Configuration//标记该类是一个配置类
public class mainConfig {
@Bean(value = "person1")//指定将Person对象放入IOC容器中的 且指定bean名称为person1
public Person person(){
return new Person();
}
}
2.包扫描的方式 @ComponentScan
@Controller
public class BookController {
}
@Repository
public class BookDao {
}
public interface BookService {
}
@Service
public class BookServiceImpl implements BookService {
}
@Configuration //标记该类是一个配置类
@ComponentScan(value = {"com.shilei.atguigu.bean"})//指定扫描的包
public class mainConfig {
@Bean
public Person person(){
return new Person();
}
}
测试
@Test
public void method2(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(mainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String str : beanDefinitionNames){
System.out.println(str);
}
}
结果
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
bookController
bookDao
bookServiceImpl
person
@ComponentScan 扩展功能
过滤策略
excludeFilters参数代表过滤一些bean
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)} //过滤掉类上@Controller注解修饰的
includeFilters参数代表只包含一些bean 适用于这条规则需要指定参数useDefaultFilters = false
@ComponentScan.Filte 过滤策略
FilterType.ANNOTATION 根据注解过滤
FilterType.ASSIGNABLE_TYPE 根据给定的类型过滤
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}) //过滤BookService类型的类 使用这个过滤器无需标注基本注入IOC容器的注解 只要在扫描的包中都会生效
FilterType.ASPECTJ 使用ASPECTJ 表达式
FilterType.REGEX 使用正则表达式过滤
FilterType.CUSTOM 自定义过滤
使用自定义过滤器需要类实现TypeFilter接口
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
返回true代表匹配成功
参数介绍 @param metadataReader the metadata reader for the target class 当前类的信息
@param metadataReaderFactory a factory for obtaining metadata readers
for other classes (such as superclasses and interfaces) 其他类的信息
@ComponentScan 注解在JDK1.8 之后可以使用多个修饰一个类进行多个包扫描
之前 可使用@ComponentScans
@Scope指定作用范围
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE 多实例 使用时调用 多次
* @see ConfigurableBeanFactory#SCOPE_SINGLETON 单实例 默认 启动时调用构造方法 一次
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST 同一个请求一个实例
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION 同一个session 一个实例
@Lazy
只针对单实例bean 第一次使用时调用 一次
@Conditional
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
参数中要实现Condition的类
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
参数说明
// context 上下文信息
// metadata 注释信息
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
//IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//获取类加载器
ClassLoader classLoader = context.getClassLoader();
//获取当前环境信息
Environment environment = context.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
@Import
1.@Import({Person.class,Color.class}) 导入组件 bean名默认为全类名
2. 可以添加 ImportSelector 的实现类进行导入
public interface ImportSelector {
//返回值 导入容器中的组件的全类名
//AnnotationMetadata importingClassMetadata 标注@Import注解类的所有注解信息
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
3.添加 ImportBeanDefinitionRegistrar 的实现类
public interface ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata annotation metadata of the importing class 当前类的注解信息
* @param registry current bean definition registry 注册类 可以自定义注册bean
*/
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class);
registry.registerBeanDefinition("pp",rootBeanDefinition);
}
使用FactoryBean
public class MyFactoryBean implements FactoryBean<Person> {
//创建一个对象添加到IOC容器中
public Person getObject() throws Exception {
return new Person();
}
//对象类型
public Class<?> getObjectType() {
return Person.class;
}
//是否单例
public boolean isSingleton() {
return true;
}
}
@Bean //bean 名字还是myFactoryBean 类型是Person 获取bean是bean名字前加& 获取的类型是MyFactoryBean
public MyFactoryBean myFactoryBean(){
return new MyFactoryBean();
}
总结
给容器中注册组件
1.包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
2.@Bean
3.@Import
1)@Import(要导入的组件)
2)ImportSelector
3) ImportBeanDefinitionRegistrar
4.使用Spring提供的FactoryBean 工厂bean