一、SpringBoot原理篇。
(1)自动配置。
(1.1)bean加载方式。
(1.1.1)xml方式。(适用自定义bean与第三方bean)
(1.1.2)注解方式+组件扫描。(适用于自定义bean)
(1.1.3)@Bean方式+将类定义为bean+组件扫描。(适用自定义bean与第三方bean)
(1.1.4)@Import。
注意:@Import导入的bean的名称是全路径类名,其他注解只是类名(首字母小写)。
(1.1.5)使用上下文对象注册bean对象。
注意:AnnotationConfigApplicationContext对象才有注册bean的方法,其他的对象没有。
(1.1.6)导入实现了ImportSelector接口的类,实现对导入源的编程式处理。
@Import(MyImportSelector.class)在SpringConfig6上面,所以SpringConfig6类是MyImportSelector类的元数据。
@Configuration
//@ComponentScan(basePackages = "com.itheima")
@Import(MyImportSelector.class)
public class SpringConfig6 {
}
public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata metadata) {System.out.println("================");System.out.println("提示:"+metadata.getClassName());System.out.println(metadata.hasAnnotation("org.springframework.context.annotation.Configuration"));Map<String, Object> attributes = metadata.getAnnotationAttributes("org.springframework.context.annotation.ComponentScan");System.out.println(attributes);System.out.println("================");//各种条件的判定,判定完毕后,决定是否装在指定的beanboolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration");if(flag){return new String[]{"com.itheima.bean.Dog"};}return new String[]{"com.itheima.bean.Cat"};}
}
(1.1.7)导入实现了ImportBeanDefinitionRegistrar接口的类。
@Import({BookServiceImpl1.class, MyPostProcessor.class, MyRegistrar2.class, MyRegistrar.class})
public class SpringConfig8 {
}
(1.1.8)导入实现了BeanDefinitionRegistryPostProcessor接口的类。
理解: 等BeanDefinitionRegistry注册完所有bean之后,BeanDefinitionRegistryPostProcessor才会开始执行,如果遇到同名的则会覆盖之前的。
@Import({BookServiceImpl1.class, MyPostProcessor.class, MyRegistrar2.class, MyRegistrar.class})
public class SpringConfig8 {
}
(1.1.9)创建上下文对象时指定配置类。(该方式等于@Import(xxx.class))
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig3.class);
提示:若创建上下文对象的时候不指定该类(即需要被组件扫描发现是配置类),则需加上@Configuration注解声明该类为配置类。
@ComponentScan({"com.itheima.bean","com.itheima.config"})
public class SpringConfig3 {@Beanpublic DogBean dog(){return new DogBean();}
}
public class App3 {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig3.class);String[] names = ctx.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}System.out.println(ctx.getBean("dog"));}
}
(1.1.10)FactoryBean接口(制造接口泛型类型的bean,本质@Bean声明,返回是泛型类型)。
注意:虽然返回是DogFactoryBean类型,但实际上返回的是泛型的类型。(原理暂不清楚)
public class DogFactoryBean implements FactoryBean<Dog> {@Overridepublic Dog getObject() throws Exception {Dog d = new Dog();//.........return d;}@Overridepublic Class<?> getObjectType() {return Dog.class;}@Overridepublic boolean isSingleton() {return true;}
}
@ComponentScan({"com.itheima.bean","com.itheima.config"})
public class SpringConfig3 {//该方法与下面的方法只能存在一个。(因为两个方法返回值都是Dog类型)@Beanpublic DogFactoryBean dog(){return new DogFactoryBean();}//这个返回的是Dog类型(Dog是接口),该方法与下面的方法只能存在一个。(因为两个方法返回值都是Dog类型)
// @Bean
// public Dog dog(){
// return new Dog();
// }}
提示:传递的泛型是Book,即@Bean出来的实际是Book对象。
(1.1.11)配置文件+配置类 = 搭配使用。
提示:个人觉得,跟配置文件中注解扫描该配置类,然后上下文对象中指定配置文件是一样的。
ApplicationContext ctx = new ClassPathXmlApplicationContext("SpringConfig2.xml");
(1.1.12)@Configuration注解的不一样。
@Configuration默认创建的是代理对象,在获取代理对象后,调用该对象里面的方法(有@Bean标记的方法)的时候先去IOC容器中获取返回(即得到的都是同一个对象)。
注意:proxyBeanMethods属性默认是ture,如果是false,则不是代理对象。
(1.1.13)小结。
注意:@Import导入的bean的名称是全路径类名,其他注解只是类名(首字母小写)。
提示:6、7、8这上使用@Import导入实现接口的类,实际该类不会被注册到容器里面,只会注册接口方法中定义的需要被注册到容器的bean。
(1.2) Bean的加载控制。
(1.2.1)bean加载控制方式。
提示:能够对bean的加载进行控制的基本都是编程式的。
(1.2.2)bean的加载控制(编程式)。
@Import(MyImportSelector.class)
public class SpringConfig {
}
(1.2.3)bean的加载控制(注解)。
@ConditionalOnClass(Mouse.class):检测是否存在这个类,其实使用类型没意义,需要使用字符串才不报错。(这是关于项目有没有该类)
@ConditionalOnBean(name = "com.itheima.bean.Mouse"):bean名为mouse(使用@Component注解标记),这也满足。(这是在IOC容器中有没有该对象)
@ConditionalOnBean(name = "jerry"):则名称必须要相同(使用@Component(“jerry”)标记)。
注意:注解需要导入springboot基本依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.4</version></dependency>
注意:还可以在类上就行判断是否需要加载为bean:
@Component("tom")
@ConditionalOnBean(name = "jerry")
//@ConditionalOnWebApplication
@ConditionalOnNotWebApplication
public class Cat {
}
(1.3)bean依赖属性配置。
总结起来就是:如果配置文件中有值则使用,如果没有则使用默认值。
@EnableConfigurationProperties(CartoonProperties.class)
注解的作用是将 CartoonProperties
类注册为一个 Spring Bean。