@[TOC]
1 包扫描+组件标注注解
1.1 简单使用
- 加
@ComponentScan
注解@ComponentScan("com.yunfeng.spring2") public class MainConfig { }
- 在自己创建的类上加
@Controller
、@Service
、@Repository
、@Component
注解@Controller public class BookController { }
1.2 ConponentScan自定义扫描规则
- 创建
MyComponentScanTypeFilter
并实现TypeFilter
```java
package com.yunfeng.spring2.config;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
/**
自定义ComponentScan扫描规则
*/
public class MyComponentScanTypeFilter implements TypeFilter {/*
- @param metadataReader 读取当前扫描类的信息
- @param metadataReaderFactory 读取其他任何类的信息
- @return
- @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前正在扫描类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类路径)
Resource resource = metadataReader.getResource();
//获取类名
String className = classMetadata.getClassName();
if (className.contains("mapper")) {
}else {//true 代表匹配 return true;
}//false 代表不匹配 return false;
}
}
* 测试
```java
package com.yunfeng.spring2.config;
import com.yunfeng.spring2.entity.Person;
//import com.yunfeng.spring2.mapper.BookMapper;
import org.springframework.context.annotation.*;
//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Repository;
//import org.springframework.stereotype.Service;
@Configuration
//@ComponentScan(value = "com.yunfeng.spring2",includeFilters = {
// @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})
//},useDefaultFilters = false)
@ComponentScans(value = {
@ComponentScan(value = "com.yunfeng.spring2",includeFilters = {
//注解类型过滤
// @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class}),
//类类型过滤
// @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookMapper.class}),
//自定义过滤
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyComponentScanTypeFilter.class})
},useDefaultFilters = false)
})
public class MainConfig {
@Bean(value = "person")
public Person addPerson(){
return new Person("胡思源",16);
}
}
2 @Bean导入的第三方包里面的组件
2.1 简单使用
@ComponentScan(value = "com.yunfeng.spring2")
public class MainConfig {
@Bean(value = "person")
public Person addPerson(){
return new Person("胡思源",16);
}
}
2.2 自定义条件注入
- 新建
WindowsCondition
并实现Condition
```java
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class WindowsCondition implements Condition {
/**
*
* @param context 判断条件能使用的上下文(环境)
* @param annotatedTypeMetadata 注释信息
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1、能获取到IOC使用的beanfactory(创建对象并装配的工厂)
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3、获取当前环境信息
Environment environment = context.getEnvironment();
//4、获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
if (property.contains("Windows")){
return true;
}
return false;
}
}
* 可以在方法上使用也可以在类上使用
```java
@Conditional(WindowsCondition.class)
@Bean(value = "bill")
public Person addPerson1(){
return new Person("bill",76);
}
- 测试
@Test public void test03(){ Environment environment = context.getEnvironment(); System.out.println(environment.getProperty("os.name")); Map<String, Person> persons = context.getBeansOfType(Person.class); System.out.println("persons = " + persons); }
3 @Import快速给容器中导入一个组件
3.1 @Import直接导入
@Configuration @Import({ Color.class, Red.class}) public class MainConfig2 { }
3.2 使用ImportSelector返回需要导入的组件的全类名数组
- 新建
MyImportSelector
并实现ImportSelector
```java
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
// 自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
/**
* 自定义逻辑返回需要导入的组件
* @param annotationMetadata 当前标注@Import注解的类的所有注解信息
* @return 返回值,就是导入到容器中的组件全类名
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// annotationMetadata.
return new String[]{"com.yunfeng.spring2.config.Blue","com.yunfeng.spring2.config.Yellow"};
}
}
* 在`@Import`中使用
```java
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class})
public class MainConfig2 {}
3.3 使用ImportBeanDefinitionRegistrar自定义注入Bean
- 新建MyImportBeanDefinitionRegistrar并实现ImportBeanDefinitionRegistrar
```java
import com.yunfeng.spring2.entity.RainBow;
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 {
/*
* @param annotationMetadata 当前类的注解信息
* @param registry BeanDefinition注册类:
* 调用BeanDefinitionRegistry.registerBeanDefinition手工注册类进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
boolean definition1 = registry.containsBeanDefinition("com.yunfeng.spring2.entity.Red");
boolean definition2 = registry.containsBeanDefinition("com.yunfeng.spring2.entity.Blue");
if (definition1 && definition2){
//指定bean定义信息
RootBeanDefinition definition = new RootBeanDefinition(RainBow.class);
//设置非单例
definition.setScope("prototype");
//注册一个Bean,指定bean名
registry.registerBeanDefinition("RainBow",definition);
}
}
}
* 使用
```java
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}
4 使用FactoryBean<T>
注入组件
- 创建
ColorFactoryBean
并实现FactoryBean<Color>
```java
import org.springframework.beans.factory.FactoryBean;
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
//true为单实例
@Override
public boolean isSingleton() {
return true;
}
}
* 使用`@Bean`注入
```java
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
- 测试
@Test public void test04(){ String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } //从工厂中获取的是getObject创建的对象 Object colorFactoryBean = context.getBean("colorFactoryBean"); System.out.println(colorFactoryBean.getClass()); //获取工厂Bean本身 Object colorFactoryBean2 = context.getBean("&colorFactoryBean"); System.out.println(colorFactoryBean2.getClass()); }