(6).按需加载自动配置项
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在
spring-boot-autoconfigure
包里面
如果我们查看源码的时候爆红,不是因为我们哪里写错了,而是我们的SpringBoot是按需配置的,没有使用上(使用依赖)就会爆红。
2.IOC容器功能
2.1、组件添加
(1).@Configuration
- 基本使用
- Full模式与Lite模式
- 示例
- 最佳实战
- 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
1.我们使用SpringMVC的时候如何进行组件添加的
在resources目录下创建 beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 1.指定我们的人类实体类并赋值id --> <bean id="user01" class="com.jsxs.bean.User"> <!-- 2.给我们实体类进行默认赋值的操作 --> <property name="name" value="李明"></property> <property name="age" value="12"></property> </bean> <!-- 3.指定宠物实体类并赋值id --> <bean id="cat" class="com.jsxs.bean.Pet"> <property name="name" value="哈吉米"></property> </bean> </beans>
2.现在我们省去了配置文件,直接使用@Configuration注解即可
package com.jsxs.config; import com.jsxs.bean.Pet; import com.jsxs.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author Jsxs * @Date 2023/7/1 12:30 * @PackageName:com.config * @ClassName: MyConfig * @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的, * @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。 * @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列 * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】 * 组件依赖必须使用Full模式默认。其他默认是否Lite模式 * * @Version 1.0 */ @Configuration(proxyBeanMethods=false) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml public class MyConfig { @Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签 // 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id public User user01() { // FULL模式人拥有宠物 return new User("李明",12,this.cat()); } @Bean("tom") // 相当于我们配置文件的bean标签 public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id return new Pet("哈吉米"); } }
- 什么时候用到Full模式或List模式呢?
组件依赖必须使用Full模式默认。其他默认是否Lite模式。通俗的讲就是如果这个容器下面没人用了我们就设置成false,如果仍然有人是用的话,我们就设置成true。
- 区别: 设置成fasle会跳过检查是否容器中已经存在,提升性能。
列子: 用户拥有容器中注册的哈吉米猫,我们要使用FULL模式,因为要保证用户有的是唯一的,即用户拥有的哈吉米猫和容器中组件的哈吉米猫是一样的。
User.java
package com.jsxs.bean; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @Author Jsxs * @Date 2023/7/1 12:11 * @PackageName:com.jsxs.bean * @ClassName: User * @Description: TODO * @Version 1.0 */ @AllArgsConstructor @NoArgsConstructor @Data public class User { private String name; private int age; // private Pet pet; }
config.java 设置为FULL模式
package com.jsxs.config; import com.jsxs.bean.Pet; import com.jsxs.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author Jsxs * @Date 2023/7/1 12:30 * @PackageName:com.config * @ClassName: MyConfig * @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的, * @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。 * @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列 * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】 * 组件依赖必须使用Full模式默认。其他默认是否Lite模式 * * @Version 1.0 */ @Configuration(proxyBeanMethods=true) ⭐// 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml public class MyConfig { @Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签 // 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id public User user01() { // FULL模式人拥有宠物 return new User("李明",12,this.cat()); } @Bean("tom") // 相当于我们配置文件的bean标签 public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id return new Pet("哈吉米"); } }
(2).@Bean、@Component、@Controller、@Service、@Repository
1.SpringMVC提供的这些注解,只要在SpringBoot扫描包的范围内仍然可以进行注册组件。
1. @Bean 注册配置类组件 2. @Component 除了配置类组件不能使用,其余万能 3. @Controller 控制层组件 4. @Service 业务层组件 5. @Repository 实体类层组件
(3).@ComponentScan、@Import
1.@ComponentScan 组件
通过这个注解我们可以手动的更改SpringBoot默认的扫描路径。
2. @Import
用法: 1. @imoort 用于放在容器中组件类上。 用途 2. @imoort 用于给容器中导入 自定义组件或第三方组件 结论 3. @import引入组件和手动添加组件结果都添加到容器中去了,但是获取到的组件名有点区别: 引入的获得的名字是全限定名,手动的不是全限定名。
package com.jsxs.config; import com.jsxs.bean.Pet; import com.jsxs.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * @Author Jsxs * @Date 2023/7/1 12:30 * @PackageName:com.config * @ClassName: MyConfig * @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的, * @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。 * @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列 * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】 * 组件依赖必须使用Full模式默认。其他默认是否Lite模式 * * @Version 1.0 */ @Import({User.class}) ⭐⭐ @Configuration(proxyBeanMethods=true) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml public class MyConfig { @Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签 // 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id public User user01() { // FULL模式人拥有宠物 return new User("李明",12,this.cat()); } @Bean("tom") // 相当于我们配置文件的bean标签 public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id return new Pet("哈吉米"); } }
package com.jsxs; import com.jsxs.bean.Pet; import com.jsxs.bean.User; import com.jsxs.config.MyConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; /** * @Author Jsxs * @Date 2023/7/1 9:53 * @PackageName:com.jsxs * @ClassName: MainSpringApplication * @Description: TODO * @Version 1.0 */ @SpringBootApplication public class MainSpringApplication { public static void main(String[] args) { // 1.返回的是我们的IOC容器 ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args); // 2.我们查看IOC容器里面都有哪些组件 String[] benas = run.getBeanDefinitionNames(); for (String bena : benas) { System.out.println(bena); } // 3.从IOC容器中获取组件,结果为true证明是单实列的。Bean是一个组件 Pet tom1 = run.getBean("tom", Pet.class); Pet tom2 = run.getBean("tom", Pet.class); System.out.println("组件"+(tom1==tom2)); // == 比较的是地址 // 4.配置类(类名)也是一个组件 MyConfig bean = run.getBean(MyConfig.class); System.out.println(bean); // 如果能打印出来,就署名我们通过类名获取一个组件成功 // 5.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列 User user1 = bean.user01(); User user2 = bean.user01(); System.out.println(user1==user2); //如果被代理就为true,不被代理就为false // 6.验证Full模式 User user01 = (User) run.getBean("user01",User.class); //从容器中获取user Pet pet = user01.getPet(); Pet tom = run.getBean("tom", Pet.class); //假如不是代理的,那么在这里就会重新生成一个bean,如果是代理的就不会重新生成 System.out.println("验证Full:"+(pet==tom)); // 7.验证import引入组件 String[] type = run.getBeanNamesForType(User.class);//根据类型进行获取组件 System.out.println("======="); ⭐⭐⭐ for (String s : type) { System.out.println(s); } } }