1、@Configuration和@Bean注册
@Configuration:使当前类成为一个配置类;
@Bean:给容器注册一个实例,类型为返回值的类型,id默认是用方法名作为id;
- pom.xml引用:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
- MainConfig类:
@Configuration
public class MainConfig {
@Bean
public Bean1 bean1() {
return new Bean1();
}
}
- Bean1类:
public class Bean1 {
}
- Test1类:
public class Test1 {
@SuppressWarnings("resource")
@Test
public void test1() {
// 获取spring上下文
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Bean1 b = context.getBean(Bean1.class);
System.out.println(b);// 输出:sprint_test1.dav.bean.Bean1@628016f7
}
}
2、@ComponentScans注册
@ComponentScan value:指定扫描的包路径;
- MainConfig类:
@Configuration
@ComponentScan(value = "com.dav")
public class MainConfig {
}
- Service类
@org.springframework.stereotype.Service
public class Service {
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println(context.getBean(com.dav.service.Service.class));// com.dav.service.Service@1df41e93
}
3、自定义TypeFilter指定过滤规则
excludeFilters = Filter[] :指定扫描的时候按照指定规则排除组件
includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照指定类型
FilterType.REGEX:使用正则表达式
FilterType.CUSTOM:使用正则表达式
useDefaultFilters:true(使用默认的过滤器),false(使用自定义的过滤器)
- MainConfig类:
@Configuration
@ComponentScans(value = {@ComponentScan( value = "com.dav", includeFilters = {
@Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class)
},useDefaultFilters = false)})
public class MainConfig {
}
- MyTypeFilter类:
public class MyTypeFilter implements TypeFilter{
/**
* metadataReader:读取到的当前正在扫描的类信息
* metadataReaderFactory:可以获取其他类信息
*/
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("er")) {
System.out.println("className--" + className);
// 输出:
// className--com.dav.config.MyTypeFilter
// className--com.dav.service.Service
return true;
}
return false;
}
}
- Dao类:
@Repository
public class Dao {
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("----" + context.getBean(Dao.class));// 没有输出
}
4、@Scope和@Lazy
调整作用域
singleton:单实例(默认)>ioc容器启动会调用方法创建对象放到ioc容器,后续获取是从容器拿;
prototype:多实例>ioc容器启动不会调用方法创建对象,后续获取才会调用方法创建对象;
request:同一次请求创建一个实例;
session:同一个会话创建一个实例;
懒加载:
@Lazy
单实例bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象.第一次使用时创建对象,并初始化;
- MainConfig类:
@Configuration
@ComponentScans(value = {@ComponentScan( value = "com.dav", includeFilters = {
@Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class)
},useDefaultFilters = false)})
public class MainConfig {
@Bean
@Scope(value = "prototype")
@Lazy
public Bean1 bean1() {
System.out.println("getBean....");
return new Bean1();
}
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("获取spring上下文");
Bean1 a = context.getBean(Bean1.class);
Bean1 b = context.getBean(Bean1.class);
System.out.println(a == b);
}
- 在初始化容器的时候并没有创建实例,而是在调用的时候创建
5、@Conditional按照条件注册
满足当前条件,这个类中配置的所有实例注册才能生效
- SystemCondition类:
如果当前系统是linux系统则注册实例
public class SystemCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 1、获取到ioc使用的bean工厂
ConfigurableBeanFactory factory = context.getBeanFactory();
// 2、获取类加载器
context.getClassLoader();
// 3、获取运行环境
Environment environment = context.getEnvironment();
// 4、获取bean定义的注册类
context.getRegistry();
String property = environment.getProperty("os.name");
if(property.contains("linux")) {
return true;
}
return false;
}
}
- MainConfig类:
@Conditional({SystemCondition.class})
@Configuration
public class MainConfig {
@Bean
public Bean1 bean1() {
System.out.println("getBean....");
return new Bean1();
}
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("获取spring上下文");
Bean1 a = context.getBean(Bean1.class);
System.out.println(a);// 没有输出
}
6、@Import导入一个实例
1.@Import({类.class})
2.ImportSelector: 返回需要导入的组件的全类名数组;
3.ImportBeanDefinitionRegistrar:手动注册bean到容器中;
- Bean2类:
public class Bean2 {
}
- Bean3类:
public class Bean3 {
}
- Bean4类:
public class Bean4 {
} - MyImportSelect类:
public class MyImportSelect implements ImportSelector {
/**
* AnnotationMetadata:当前标注@Import注解的类的所有注解信息
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 不要返回null,会报空指针异常
return new String[] {"com.dav.bean.Bean1","com.dav.bean.Bean2"};
}
}
- MainConfig类:
@Configuration
@Import({MyImportSelect.class,Bean3.class,MyImportBeanDefinitionRegister.class})
public class MainConfig {
}
- MyImportBeanDefinitionRegister类:
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar{
/**
* AnnotationMetadata:当前类注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 是否包含某个bean
boolean tmp = registry.containsBeanDefinition("com.dav.bean.Bean4");
if(!tmp) {
// 指定bean的注册信息
RootBeanDefinition beanDefinition = new RootBeanDefinition(Bean4.class);
// 注册bean
registry.registerBeanDefinition("bean4", beanDefinition);;
}
}
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("获取spring上下文");
Bean1 a = context.getBean(Bean1.class);
Bean2 b = context.getBean(Bean2.class);
Bean3 c = context.getBean(Bean3.class);
Bean4 d = context.getBean(Bean4.class);
System.out.println(a + "-" + b + "-" + c + "-" + d);
// 输出:
// [email protected]@[email protected]@20de643a
}
7、使用FactoryBean注册
使用Spring提供的FactoryBean;
1.默认获取的是工厂bean调用getObject创建的对象;
2.要获取工厂bean本身,需要在id前面&符号(&colorFactoryBean)
- Bean1FacotryBean类:
//创建一个Spring定义的FactoryBean
public class Bean1FacotryBean implements FactoryBean<Bean1> {
// 返回一个Bean1对象
public Bean1 getObject() throws Exception {
return new Bean1();
}
public Class<?> getObjectType() {
return Bean1.class;
}
// 控制是否单例(true:单例,false:多实例)
public boolean isSingleton() {
return true;
}
}
- MainConfig类
@Configuration
public class MainConfig {
@Bean
public Bean1FacotryBean bean1FacotryBean() {
return new Bean1FacotryBean();
}
}
- Test1类:
@Test
public void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Object object = context.getBean("bean1FacotryBean");
System.out.println("bean类型:"+object.getClass());// bean类型:class com.dav.bean.Bean1
object = context.getBean("&bean1FacotryBean");
System.out.println("bean类型:"+object.getClass());// bean类型:class com.dav.condition.Bean1FacotryBean
}