SpringBoot:容器功能
组件添加
1.@Configuration
个人总结:
@Configuration告诉springboot这是一个配置类,相当于代替配置文件
@Bean 就当前方法给容器注册组件(单实例)
proxyBeanMethods = true 代理对象调用方法,比如调用user,springboot 会去容器中找 无论调用多少次都是那一个(单实例)
proxyBeanMethods = false @Bean方法被调用返回的组件都是新创建的 都不一样
Full(proxyBeanMethods = true)
Lite(proxyBeanMethods = false)
配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
假如有两个实例类,user和pet,user中一个属性 Pet pet
即: //user组件依赖了Pet组件 zhangsan.setPet(tomcatPet()); 这个时候必须使用ull模式!
#############################Configuration使用示例######################################################
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
*
*
*/
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
################################@Configuration测试代码如下########################################
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1);
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}
2.@Bean、@Component、@Controller、@Service、@Repository
根据它们的源码可以看到,Controller、Service、Repository其本质就是Component。
它存在的本质只是给开发者看的,对Spring而言它们就都是Component。
@Controller 控制层类,@Service 业务层类,@Repository 持久层类,@Component 无法归类到前3种时就称为组件。
3、@ComponentScan、@Import
ComponentScan 配置包扫描的
@Import({User.class, DBHelper.class}) * 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
* 4、@Import({User.class, DBHelper.class})
* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*/
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
测试类:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
String[] beanNamesForType = run.getBeanNamesForType(User.class);
for(String s:beanNamesForType){
System.out.println(s);
}
DBHelper bean1 = run.getBean(DBHelper.class);
System.out.println(bean1);
}
}
4.@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
如上图
ConditionalOnBean 当容器中有某个bean时干某些事
ConditionalOnMissingBean 当容器中没有某个Bean时干某些事
ConditionalOnClass 当容器中有某个类的时候 才去干某个事
ConditionalOnMissingClass 当容器中没有某个类的时候 才去干某个事
ConditionalOnResource 当项目的类路径里面存在某些资源的时候 才干什么
ConditionalOnResources 当java的版本号为多少时 才 干什么
ConditionalOnWebApplication 当应用是web应用的时候干什么
ConditionalOnNotWebApplication 当应用不是web应用的时候干什么
ConditionalOnProperty 当配置文件配置了某些属性 才干某些事情
等等1
实例:
当容器中没有user01的时候才会执行下面的操作
@Configuration
@ConditionalOnMissingBean(name = "user01")
public class MyConfig{
@Bean
public User user01(){
return new User();
}
@Bean("pet")
public Pet pet(){
return new Pet("123");
}
}
原生配置文件引入
在配置文件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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="haha" class="com.atguigu.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
然后在类中使用@ImportResource("classpath:******.xml")引入配置文件
配置绑定
如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用;
原生java语言:
public class getProperties {
public static void main(String[] args) throws FileNotFoundException, IOException {
Properties pps = new Properties();
pps.load(new FileInputStream("a.properties"));
Enumeration enum1 = pps.propertyNames();//得到配置文件的名字
while(enum1.hasMoreElements()) {
String strKey = (String) enum1.nextElement();
String strValue = pps.getProperty(strKey);
System.out.println(strKey + "=" + strValue);
//封装到JavaBean。
}
}
}
@ConfigurationProperties
@Component + @ConfigurationProperties
@Component 让实例类实例化到容器中,只有在springboot中注册,才能使用其提供的强大功能
@ConfigurationProperties 通过设置prefix属性找到配置文件中的对应的key 取到value值从而赋值给对应的属性
配置文件application.xml 中
mypet.name = dog
Pet.java
@Component //只有在springboot中注册,才能使用springboot提供的强大功能
@ConfigurationProperties(prefix = "mypet")
public class Pet {
private String name;
//getter
//setter
//toString
}
test.java
@Autowired
Pet pet;
@RequestMapping("/car")
public Pet pet(){
return pet;
}
运行主程序
@EnableConfigurationProperties + @ConfigurationProperties
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
@EnableConfigurationProperties
//1、开启Car配置绑定功能 //2、把这个Car这个组件自动注册到容器中//3.一般写在配置类里面,因为配置类肯定已经注册在了容器中!
写了这个注解就不用再pet.java上面写@Component,适用于:
有时候这个“pet.java”使用的第三方包里面的,无法加@Component