使用注解方式注册Bean 新建config包,增加配置类BeanConfig
@Configuration
public class BeanConfig {
@Bean
public Person person(){
Person person = new Person();
person.setName(“Stark”);
person.setAge(40);
return person;
}
}
@Configuration:标识为一个配置类,等同于配置文件 @Bean:给容器注册一个Bean,类型为返回值的类型,bean id为返回名 SingleBeanContainerTest中新增方法,在main方法中执行
public static void getBeanByAnno(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
Person person = (Person) context.getBean(“person”);
System.out.println(person);
String[] beanNamesForType = context.getBeanNamesForType(Person.class);
for (String s : beanNamesForType) {
System.out.println(“Bean id:” + s);
}
}
控制台输出
修改BeanConfig中@Bean注解下的方法的方法名为stark
@Bean
public Person stark(){
Person person = new Person();
person.setName(“Stark”);
person.setAge(40);
return person;
}
再次运行SingleBeanContainerTest的mian方法,控制台报错No bean named ‘person’ available
这是因为代码中获取的bean的id为person,而配置了中@Bean注解下的方法名也就是bean的id为stark,所以出现报错,更改getBean(“person”)为getBean(“stark”),再次执行,获取成功
除了修改@Bean注解下的方法名来定义Bean的id,也可以通过@Bean(“thor”)的方式来定义Bean的名称
IoC容器的数据结果为Map,注册Bean是就是往Map里面添加数据,使用put(“key”,value),key为Bean的id,value就是对象,
Section 03 - XML与注解批量注册Bean
@CompponmentScan 代替@Bean 分别新增controller,service,dao三个package,并增加响应的类,通过@Controller,@Service,@Repository三个注解将三个类声明为Bean
@Controller
public class PersonController {
}
@Service
public class PersonService {
}
@Repository
public class PersonDao {
}
修改BeanConfig,增加@ComponentScan注解,将com.citi包下面的所有Bean都扫描到BeanConfig这个配置类中,就相当于XML配置文件中有许多bean标签,好处是不用一个个写bean标签,通过一个注解可以扫描所有的Bean
@Configuration
@ComponentScan(basePackages = “com.citi”)
public class BeanConfig {
}
测试IoC容器是否实例化扫描到的Bean,新增一个ComponentScanTest测试类
public class ComponentScanTest {
@Test
public void getBeansByScan(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
控制台输出如下,自定义的三个类,包括BeanConfi本身都被容器实例化
entity包中的Person类没有被实例化,是因为Person类上没有添加注解,也即是没有配置bean标签,所以没有注册到容器中,也就没有被实例化,给Person实体类添加一个@Component注解,标识为一个Bean,再次执行测试方法,控制台打印结果如下,Person类被实例化
@ComponentScan源码
includeFilters()的使用
includeFilters()和excludeFilters()返回都是一个Filter数组
FilterType是一个枚举类,默认是ANNOTATION,注解方式
修改BeanConfig代码,增加includeFilters(),只扫描com.citi包下面的@Controller,@Service注解标识的Bean,一定不要忘记useDefaultFilters = false
@Configuration
@ComponentScan(basePackages = “com.citi”,
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
},
useDefaultFilters = false)
public class BeanConfig {
}
执行测试,控制台输出只包含了@Controller,@Service注解的Bean,@Componet和@Repository注解标识的类并没有被容器管理
Plus:为什么使用includeFilters时,要配置useDefaultFilters = false?
当useDefaultFilters = true时,进入到registerDefaultFilters()方法中
该方法中将@Component注解的Bean都加入到includeFilters中,而@Controller,@Service,@Repository都是基于@Component的注解,所有useDefaultFilters = true会导致设置是扫描@Controller和@Service注解的Bean不生效
使用excludeFilters(),将BeanConfig中includeFilters改为excludeFilters(),并且useDefaultFilters = true,执行测试,可以看出只包含了除了@Controller,@Service标注的Bean之外的其他Bean的实例化对象
使用FilterType枚举类中的ASSIGNABLE_TYPE进行过滤Bean,修改BeanConfig为如下,表示触PersonController和PersonService之外的其他Bean
@Configuration
@ComponentScan(basePackages = “com.citi”,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {PersonController.class, PersonService.class})
},
useDefaultFilters = true)
public class BeanConfig {
}
使用自定义的FilterType,在config包下新增CustTypeFilter,继承TypeFilter
public class CustTypeFilter 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();
// 扫描的类
System.out.println(“------>” + className);
// 过滤条件,return true表示过滤掉符合这个条件的Bean
if (className.contains(“service”)){
return true;
}
return false;
}
}
除了@ComponentScan之外还可以添加@ComponentScans,也就是多个@ComponentScan
使用了两个@ComponentScan注解,一个是去除自定义的Bean,即bean id包含“service”字符串的Bean,另外一个使用Annotation 类型的Filter,去除@Controller注解标记的Bean
@ComponentScans({@ComponentScan(basePackages = “com.citi”,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {CustTypeFilter.class})
},
useDefaultFilters = true),
@ComponentScan(basePackages = “com.citi”,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
},
useDefaultFilters = true)})
public class BeanConfig {
}
这里控制台应该输出包含除了PeresonController和PersonService外的实例化对象,根据控制台打印可以看出配置的两个@ComponentScan都没有生效,这里还有待继续探索,
Section 04 - Bean的单实例和多实例
IoC容器不管是使用注解还是xml方式,默认都是单实例的,IoC容器初始化的时候就会被创建,多实例仅当bean被使用的时候才会创建 修改BeanConfi为
@Configuration
public class BeanConfig {
@Bean
public Person person(){
Person person = new Person();
person.setName(“Stark”);
person.setAge(40);
return person;
}
}
新增测试类SingleOrMultInstanceTest,执行testSingleBean()方法
public class SingleOrMultiInstanceTest {
@Test
public void testSingleBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
Person person = (Person) context.getBean(“person”);
Person person1 = (Person) context.getBean(“person”);
System.out.println(“是否为单实例:” + (person == person1));
}
}
查看输出结果,通过比较从容器中获取的两个bean是否为一个bean,默认是单实例
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
推荐学习资料
- 脑图
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
mg-oe33QRqu-1712552081177)]
[外链图片转存中…(img-p5sualtM-1712552081177)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
推荐学习资料
- 脑图
[外链图片转存中…(img-0fgjMupT-1712552081178)]
[外链图片转存中…(img-8Yq166z4-1712552081178)]
[外链图片转存中…(img-kcRtFNH2-1712552081179)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!