在看这篇文章的时候,spring注解驱动开发,一直有2个疑惑
- 1.为什么MyTypeFilter这个类,我们只是定义了这个类,并没有创建它的对象,它的方法是怎么被调用的嘞,我们知道,非static方法的调用,必须借助这个方法本身所在的类的对象完成,那我们猜测这个类是spring帮我们创建的,但是什么时候创建,怎么创建,还是要留个疑问。
- 2.没有标注@Component等注解,但是也被注入了spring容器,是什么原因?
带着以上的2个疑问,开始分析猜测,看代码:
public class MyTypeFilter implements TypeFilter {
public MyTypeFilter() {
System.out.println("我诞生了");
}
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取到当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
String className = classMetadata.getClassName();
System.out.println("通过自定义的匹配规则--->"+className);
if (className.contains("er")) {
return true;
}
return false;
}
}
@Configuration //告诉Spring这是一个配置类
//@ComponentScan(value = "org.cc")//相当于是xml配置文件里面的<context:component-scan base-package="org.cc"/>
@ComponentScans(value = {
@ComponentScan(value = "org.cc",includeFilters = {
//自定义匹配的规则,org.cc这个包下的所有类都按照这个规则去进行匹配,如果符合就注入容器,当然也包括MyTypeFilter类本身
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
},useDefaultFilters = false)
})
public class MainConfig {
//相当于xml配置文件中的<bean>标签,告诉容器注册一个bean
//之前xml文件中<bean>标签有bean的class类型,那么现在注解方式的类型当然也就是返回值的类型
//之前xml文件中<bean>标签有bean的id,现在注解的方式默认用的是方法名来作为bean的id
@Lazy
@Bean
public Person person() {
System.out.println("给容器中添加person");
return new Person("lisi",20);
}
/**
* 现在下面的两个bean注册到IOC容器是要条件的:
* 1.如果系统是windows,给容器注册("bill")
* 1.如果系统是linux,给容器注册("linus")
* @return
*/
@Bean("bill")
public Person person01() {
return new Person("Bill Gates",62);
}
@Bean("linus")
public Person person02() {
return new Person("linus",48);
}
}
首先分析第1步,这个理解了,就能明白第一个问题,在spring容器未获取之前,这个类就被实例化过,要不它的方法也不能被调用是不,这里跟进源码去看
可以看到,我们定义这个类,会被spring的注解扫描器扫描到,帮助我们去创建这个对象,然后使用这个对象的功能,这个时候,还没有被放入容器中,我们可以修改下MyTypeFilter的方法,来验证下,
改了之后的运行结果:
可以看到容器中的所有对象里,不再包含MyTypeFilter这个类。至于为啥mianConfig、person、bill、linus这几个存在容器中,是因为它们不依赖那个filter,看下图:
MyTypeFilter这里结合ComponentScan注解使用的含义是,在org.cc这个包下的所有类,只要类名里带"er"字符,就会被扫描到放进容器里面。看到这里想必就理解上面的2个问题了吧。
以前我一直有个疑惑,这个类什么时候应该我们自己去主动注入,什么时候我们不用注入就可以使用呐,以这个MyTypeFilter为例,我们继承spring提供的TypeFilter接口,在程序启动的时候,spring框架需要使用MyTypeFilter这个类,借助这个类的方法(虽然是我们写的)去判断哪些类应该注入spring容器,即这个类是spring框架要用的,自然由spring框架帮助我们实例化,然后调用对应的方法,但是像一些我们整合redis的配置类等代码,由于是spring项目启动后我们去使用这个类提供的功能,就需要我们告诉spring,你初始化容器的时候,给我整个这个类的对象,我后面会拿过来用。
其实spring的ioc就是做控制反转,将对象交由spring管理,这个框架的大部分内容都在做这块,需要继续加深理解。