Spring Boot 学习(一) Condition

通过application类中的main方法里面的run方法

@SpringBootApplication
@ServletComponentScan(basePackages = "com.sp")      //可以自动将写的servlet扫描进去  配置扫描的包
@MapperScan("com.sp.mapper")
public class BootWeb01Application {
    public static void main(String[] args) {
        SpringApplication.run(BootWeb01Application.class, args);
    }

点进去run方法可以看见它是ConfigurableApplicationContext类的实例

@SpringBootApplication
@ServletComponentScan(basePackages = "com.sp")      //可以自动将写的servlet扫描进去  配置扫描的包
@MapperScan("com.sp.mapper")
public class BootWeb01Application {

    public static void main(String[] args) {
        //这样就可以启动springboot的应用,返回spring的IOC容器
        ConfigurableApplicationContext context = SpringApplication.run(BootWeb01Application.class, args);
    }
}

与此同时可以通过context.getBean("bean的名字") 来获取对应的bean组件

 

 自定义组件

1.创建一个Pojo    User

package com.sp.bean;


import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class User {
    private String name;
    private Integer age;
}

2.创建一个Config      UserConfig

其中加入注解@Conditional用于条件判断

Conditional里的源码:
public
@interface Conditional { /** * All {@link Condition} classes that must {@linkplain Condition#matches match} * in order for the component to be registered. */ Class<? extends Condition>[] value(); }

Condition里的源码:
public interface Condition {

    /**
     * Determine if the condition matches.
     * @param context the condition context
     * @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
     * or {@link org.springframework.core.type.MethodMetadata method} being checked
     * @return {@code true} if the condition matches and the component can be registered,
     * or {@code false} to veto the annotated component's registration
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);    //若为true则会创建这个对象,若返回为false则不创建

}

创建一个UserCondition类,继承Condition接口

package com.sp.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class UserCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return false;   //默认情况下返回的是false
    }
}

3.创建一个Config用于标注为组件

package com.sp.config;


import com.sp.bean.User;
import com.sp.condition.UserCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
    @Bean
    @Conditional(UserCondition.class)   //声明Condition的类
    public User user() {
        return new User();
    }
}

测试默认为false的情况:

@SpringBootApplication
@ServletComponentScan(basePackages = "com.sp")      //可以自动将写的servlet扫描进去  配置扫描的包
@MapperScan("com.sp.mapper")
public class BootWeb01Application {

    public static void main(String[] args) {
        //这样就可以启动springboot的应用,返回spring的IOC容器
        ConfigurableApplicationContext context = SpringApplication.run(BootWeb01Application.class, args);
        Object User = context.getBean("user");//根据名字获取bean
        System.out.println(User);
    }

}

 

 改为true之后测试:

 

 

导入jedis,不导入的话自定义注解无法生效

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
</dependency>

 

public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            //导入jedis坐标后创建Bean
       boolean flag = true;
            try {
                Class<?> cls = Class.forName("redis.clients.jedis.Jedis");   //判断redis.clients.jedis.Jedis文件是否存在
} catch (ClassNotFoundException e) {
   e.printStackTrace();
  flag = false;
}
 
return flag; }

 

 

自定义注解

 

 

 将

//  @Conditional(UserCondition.class)
@ConditionOnClass("redis.clients.jedis.Jedis") //自定义注解,完成自定义注解,如果想与上面的一样可以把此注解放在自定义注解的文件上标注这注解
package com.sp.config;

import com.sp.bean.User;
import com.sp.condition.ConditionOnClass;
import com.sp.condition.UserCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {

    @Bean
//    @Conditional(UserCondition.class)
    @ConditionOnClass("redis.clients.jedis.Jedis") //自定义注解
    public User user() {
        return new User();
    }
}

 

将此注解@Conditional(UserCondition.class) 放到自定义的注解中标注

package com.sp.condition;

import org.springframework.context.annotation.Conditional;

@Conditional(UserCondition.class)
public @interface ConditionOnClass {
    String[] value();
}

 

添加原@Conditional里的注解,在对应的自定义注解上

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(UserCondition.class)
public @interface ConditionOnClass {
    String[] value();
}

 

 

改进:

    package com.sp.condition;

    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    import redis.clients.jedis.Jedis;

    import java.util.Map;

    public class UserCondition implements Condition {

        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//          1.导入jedis坐标后创建Bean
            //context   上下文对象,用于获取环境,IOC容器,ClassLoader对象
            //metadata  注解元对象,可以用于获取注解定义的属性值
//            boolean flag = true;
//            try {
//                Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
//            } catch (ClassNotFoundException e) {
//                e.printStackTrace();
//                flag = false;
//            }
//            return flag;

//          2.导入通过注解属性值value指定坐标后创建Bean

//            获取注解属性值:value
            Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
            String[] value = (String[]) map.get("value");
            boolean flag = true;
            try {
                for (String className: value) {
                    Class<?> cls = Class.forName(className);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                flag = false;
            }
            return flag;
        }
    }
View Code

 

 

@ConditionalOnProperty:    判断文件中是否有对应属性值才初始化Bean

@ConditionalOnClass:    判断环境中是否有对应字节码文件才初始化Bean

@ConditionalOnMissingBean:    判断环境中没有对应Bean才初始化Bean

posted @ 2021-07-02 23:30  YuyuFishSmile  阅读(200)  评论(0)    收藏  举报