一、 参考
04-SpringBoot自动配置-切换内置web服务器_哔哩哔哩_bilibili
二、 Condition
顾名思义:条件。有点类似于if语句,只不过是通过注解的形式来实现。
以一个实际需求来学习该原理:有一个实体类User,想要创建该实例化对象,必须导入某第三方包(这个第三方包名必须可以自己设定),否则无法创建User的实例化对象。
先看Project的结构,
- ClassCondition.java :@ConditionOnClass注解的实现类,他人不可调用。
- ConditionOnClass.java :注解,供他人调用的注解。
- UserConfig.java :起控制作用,根据程序员设定的Conditioal判断是否新建User对象并返回。
- User.java :实体类,bean类。
- SpringbootConditionApplication.java:在此文件中获取User这个bean对象
举个例子:
相当于一个水龙头流水的案例,User这个bean就是我们想接的水,UserConfig就是出水的那个管子,ClassCondition和@ConditionOnClass注解就是控制水流的水龙头,只不过ClassCondition是@ConditionOnClass注解的实际实现,外面的人使用@ConditionOnClass注解即可,不用关心水龙头里面的构造。
2.1 ClassCondition.java
实现Condition接口,需要重写一个boolean matches()方法,该方法返回true/false,返回的真值就类似于if判断的结果。
package com.itheima.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class ClassCondition implements Condition {
/**
*
* @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
* @param metadata 注解元对象。 可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
/*
//1.需求: 导入Jedis坐标后创建Bean
//思路:判断redis.clients.jedis.Jedis.class文件是否存在
boolean flag = true;
try {
Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
flag = false;
}
return flag;
*/
//2.需求: 导入通过注解属性值value指定坐标后创建Bean
//获取注解属性值 value
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
//System.out.println(map);
String[] value = (String[]) map.get("value");
boolean flag = true;
try {
for (String className : value) {
Class<?> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
flag = false;
}
return flag;
}
}
2.2 ConditionOnClass.java
这是一个注解类,右键Annotation即可新建。
里面通过@Conditional(ClassCondition.class)来和他的实现类ClassCondition.java完成绑定,外面的人直接使用@ConditionOnClass注解即可,不用关系它的实现类ClassCondition是怎么实现的,相当于一层封装。
里面有一个String数组value,这个就是用来将外面的人传递给注解的参数传递给实现类ClassCondition.java。
package com.itheima.springbootcondition.condtion;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) //运行时指定
@Documented
//下面这个注解需要特别关注,就是考这个注解将ConditionOnClass和ClassCondition绑定到一起的
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
2.3 UserConfig.java
@configuration注解对象,会自动加载其中的config,下面的config主要完成的功能就是根据程序员设定的conditional条件判断是否新建对象并返回给调用者。
在这里面使用刚才新建的注解。
package com.itheima.springbootcondition.config;
import com.itheima.springbootcondition.condtion.ClassCondition;
import com.itheima.springbootcondition.condtion.ConditionOnClass;
import com.itheima.springbootcondition.domain.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
@ConditionOnClass("com.alibaba.fastjson.JSON")
public User user(){
return new User();
}
/**
* 下面这个Case是调用现成的,不用我们自己写
* @return
*/
@Bean
@ConditionalOnProperty(name = "itcast",havingValue = "itheima")
public User user2(){
return new User();
}
}
2.4 User.java
实体对象类,自由添加即可。
package com.itheima.springbootcondition.domain;
public class User {
}
2.5 SpringbootConditionApplication.java
在此函数中调用UserConfig中的函数获取User这个bean的实例化对象。
package com.itheima.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootConditionApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args);
/*
//获取Bean,redisTemplate
Object redisTemplate = context.getBean("redisTemplate");
System.out.println(redisTemplate);
*/
Object user = context.getBean("user2");
System.out.println(user);
}
}
三、小结
大部分情况下不需要我们自己写。