二 spring-boot 高级
1.原理分析
SpringBoot 自动配置
SpringBoot 监听机制
SpringBoot 启动流程分析
SpringBoot 自动配置
Condition
Condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作。
自定义注解@Annotation
eg:需求:导入jedis坐标后,加载该bean,没导入则不加载,实现自定义注解
1.创建一个springboot项目,创建一个springboot启动类
package com.liang.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
*
* 若引入了依赖spring-boot-starter-data-redis 则程序运行正常
* 打印:org.springframework.data.redis.core.RedisTemplate@2e27d72f
*
* 若未引入依赖 则程序运行报错
* 打印:No bean named 'redisTemplate' available
*/
/**
* Object redisTemplate = context.getBean("redisTemplate");
* System.out.println(redisTemplate);
*/
/**
* 1.导入jedis坐标后,加载该bean,没导入则不加载
*/
Object user = context.getBean("User2");
System.out.println(user);
}
}
2.创建一个实体类User
package com.liang.springbootcondition.domain;
/**
* @author: Xiao Liang Zai
* @Date: 2021/8/17 10:42
* @description:
*/
public class User {
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.Condition 可以判断bean是否需要被创建
因为要判断bean是否被创建所以自定义ClassCondition类 implements Condition 重写里面的
matches()方法
package com.liang.springbootcondition.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
/**
* @author: Xiao Liang Zai
* @Date: 2021/8/17 10:50
* @description:
*/
public class ClassCondition implements Condition {
/**
* @param context 上下文对象,用于获取环境、ioc容器、classLoader对象、、、
* @param metadata 注解的元对象,可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//1.需求:1.导入jedis坐标后,加载该bean,没导入则不加载
//思路:判断redis.clients.jedis.Jedis.class文件是否存在
boolean flag = true;
try {
Class<?> aClass = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
4.自定义注解@ConditionOnClass(名称随便取)
核心注解:@Conditional(ClassCondition.class)
description:@Conditional()去加载我们自定义的ClassCondition的字节码文件
自定义注解还要导入一下三个原注解 * @Target({ElementType.TYPE, ElementType.METHOD}) @Target:注解可以加在类和方法上 * @Retention(RetentionPolicy.RUNTIME) @Retention:注解生效时机 * @Documented 生成文档
package com.liang.springbootcondition.condition;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
/**
* @author: Xiao Liang Zai
* @Date: 2021/8/17 11:05
* @description:
*/
/**自定义注解 将实现与@Conditional注解一样的功能
* 自定义注解还要导入一下三个原注解
* @Target({ElementType.TYPE, ElementType.METHOD}) @Target:注解可以加在类和方法上
* @Retention(RetentionPolicy.RUNTIME) @Retention:注解生效时机
* @Documented 生成文档
*/
@Conditional(ClassCondition.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConditionOnClass {
String[] value();
}
5.定义一个配置类UserConfig
@ConditionOnClass("redis.clients.jedis.Jedis")
description:"redis.clients.jedis.Jedis"这个为jedis的路径,会去这个路径下找Jedis.class文件
我们在注解中定义了一个
String[] value();
在实现类ClassCondition类中,在matches方法中可判断是否存在这个jedis字节码文件
//2.需求: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<?> aClass = Class.forName(className);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
flag = false;
}
return flag;
package com.liang.springbootcondition.config;
import com.alibaba.fastjson.JSON;
import com.liang.springbootcondition.condition.ClassCondition;
import com.liang.springbootcondition.condition.ConditionOnClass;
import com.liang.springbootcondition.domain.User;
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;
/**
* @author: Xiao Liang Zai
* @Date: 2021/8/17 10:43
* @description:
*/
@Configuration
public class UserConfig {
@Bean(name = "User")
@ConditionOnClass("redis.clients.jedis.Jedis") //使用自定义注解
public User user() {
return new User();
}
}