Java技术专题

Spring注解开发

2019-06-23  本文已影响1人  爱撒谎的男孩

@Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {}

@Bean

/**
 * 配置类
 */
@Configuration(value = "MyConfiguration")
public class MyConfiguration {
    /**
     * 注入一个User对象,ioc容器中的name是user,类型是User类型
     */
    @Bean
    public User user(){
        return new User(1,"name");
    }
}

属性

实例

/**
 * 配置类
 */
@Configuration(value = "MyConfiguration")
public class MyConfiguration {

    /**
     * 注入一个User对象,ioc容器中的name是user,类型是User类型
     * init是User类中的init方法,destory是User类中的destory方法
     */
    @Bean(initMethod = "init",destroyMethod = "destory")
    public User user1(){
        return new User(1,"name");
    }
}

/**
* User类
*/
public class User implements Serializable {
    private Integer id;
    private String name;

    public User(String name) {
        this.name = name;
    }

    public User(Integer id, String name) {
        System.out.println("执行构造方法");
        this.id = id;
        this.name = name;
    }

    public void init(){
        System.out.println("初始化方法");
    }

    public void destory(){
        System.out.println("销毁方法");
    }
}

@Scope

四大作用域

 /**
     * 指定多实例,每次用到都会调用
     */
    @Bean(initMethod = "init",destroyMethod = "destory")
    @Scope(value = "prototype")
    public User user1(){
        return new User(1,"name");
    }

@Conditional

/**
     * 指定多实例,每次用到都会调用
     * @Conditional 只有里面全部都匹配才会正常注入到容器中
     */
    @Bean(initMethod = "init",destroyMethod = "destory")
    @Conditional(value = {FirstCondition.class})
    public User user1(){
        return new User(1,"name");
    }
/**
 * 自定义的条件判断,实现Condition接口
 */
public class FirstCondition implements Condition {

    /**
     * 如果返回true表示符合条件,反之不符合条件
     * @param context ConditionContext对象,可以获取上下文的信息
     * @param metadata AnnotatedTypeMetadata对象,可以获取标注在该方法上面的注解信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取Environment,用来获取运行环境中的一些变量
        Environment environment = context.getEnvironment();
        //获取在properties文件中配置的参数,表示是否注入相关属性
        Boolean isAutowired = environment.<Boolean>getProperty("isAutowired", Boolean.class);
        return isAutowired;
    }
}

ConditionContext

public interface ConditionContext {

    /**
    * 获取 BeanDefinitionRegistry,可以自己手动注册对象到ioc容器中
    */
    BeanDefinitionRegistry getRegistry();

    /**
     * 获取BeanFacotory,操作ioc容器,比如获取对应的Bean,判断ioc中是否已经注入   
     */
    @Nullable
    ConfigurableListableBeanFactory getBeanFactory();

    /**
     * 返回当前的运行环境,可以获取运行环境中的一下参数,或者一些配置文件中的数据
     */
    Environment getEnvironment();

    /**
     * 获取资源加载器
     */
    ResourceLoader getResourceLoader();

    /**
     * 获取类加载器 
     */
    @Nullable
    ClassLoader getClassLoader();
}

AnnotatedTypeMetadata

public interface AnnotatedTypeMetadata {

    /**
    * 判断方法上是否有对应的注解 
    * @param annotationName 注解类的全类名,getName()
    */
    boolean isAnnotated(String annotationName);

    /**
    *  获取对应注解的全部属性的值,key是属性,value是属性的值
    * @param annotationName 注解类的全类名,getName()
    */
    @Nullable
    Map<String, Object> getAnnotationAttributes(String annotationName);

    @Nullable
    Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);

    @Nullable
    MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);

    @Nullable
    MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}

@PostConstruct

@PostConstruct
    public void init(){
        System.out.println("初始化方法");
    }

@PreDestroy

@PreDestroy
    public void destory(){
        System.out.println("销毁方法");
    }

@Import

直接导入类

@Configuration(value = "MyConfiguration")
@Import(value = {Person.class})
public class MyConfiguration {}

导入配置类

/**
 * 这是一个配置,但是并没有使用@Configuration这个注解,因此不会生效
 */
public class SecondConfiguration {
    @Bean
    public Person person(){
        return new Person();
    }
}
@Configuration(value = "MyConfiguration")
@Import(value = {SecondConfiguration.class})
public class MyConfiguration {}

指定ImportSelector

/**
 * 自定义Selector,需要实现ImportSelector
 */
public class FirstSelector implements ImportSelector {
    /**
     * 筛选逻辑,返回的是String数组(需要注入到容器中的类的全类名)
     * @param importingClassMetadata AnnotationMetadata对象,对标注了@Import这个注解的类中的所有注解信息,比如获取标注指定注解的方法
     * @return 返回的是需要注入的字符串数组(类的全类名)
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //获取@Import标注的类中被@Bean标注的方法元数据
        Set<MethodMetadata> annotatedMethods = importingClassMetadata.getAnnotatedMethods(Bean.class.getName());
        annotatedMethods.forEach(o->{
            System.out.println(o.getMethodName());
        });
        //将Person类返回去,那么将会自动注入Person
        return new String[]{Person.class.getName()};
    }
}
@Configuration
@Import(value = {FirstSelector.class})
public class MyConfiguration {}

AnnotationMetadata

public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {

    //拿到Class上标注的所有注解,依赖于Class#getAnnotations
    Set<String> getAnnotationTypes();

    // 拿到所有的元注解信息AnnotatedElementUtils#getMetaAnnotationTypes
    //annotationName:注解类型的全类名
    Set<String> getMetaAnnotationTypes(String annotationName);
    // 是否包含指定注解 (annotationName:全类名)
    boolean hasAnnotation(String annotationName);
    //这个厉害了,依赖于AnnotatedElementUtils#hasMetaAnnotationTypes
    boolean hasMetaAnnotation(String metaAnnotationName);
    // 类里面只有有一个方法标注有指定注解,就返回true
    //getDeclaredMethods获得所有方法, AnnotatedElementUtils.isAnnotated是否标注有指定注解
    boolean hasAnnotatedMethods(String annotationName);
    // 注意返回的是MethodMetadata 原理基本同上
    // .getDeclaredMethods和AnnotatedElementUtils.isAnnotated  最后吧Method转为MethodMetadata
    Set<MethodMetadata> getAnnotatedMethods(String annotationName);
}

使用ImportBeanDefinitionRegistrar手动注册

/**
 * 自定义的FirstBeanDefinitionRegistrar,需要实现ImportBeanDefinitionRegistrar
 */
public class FirstBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * 自己手动注册Bean到ioc容器中
     * @param importingClassMetadata 获取@Import标注的类上的注解信息,比如获取被指定注解标注的方法信息
     * @param registry  注册中心,可以获取指定bean的信息和手动注册bean
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //如果容器中没有Person这个Bean,就创建一个
        if (!registry.containsBeanDefinition(Person.class.getName())){
            GenericBeanDefinition beanDefinition=new GenericBeanDefinition();
            beanDefinition.setBeanClass(Person.class);
            //手动注册
            registry.registerBeanDefinition("person",beanDefinition);
        }
    }
}
@Configuration
@Import(value = {FirstBeanDefinitionRegistrar.class})
public class MyConfiguration {}

@Primary

    @Bean
    @Primary
    public User user1(){
        return new User(1,"user1");
    }
    
    //第二种
    @Primary
    @Component
    public class Person {
        private String name;
        private Integer age;
    }

@Autowired

@Controller
public class UserController {
    @Autowired
    private UserService userService;

属性

@Qualifier

@Controller
public class UserController {
    @Autowired
    @Qualifier(value = "userService")
    private UserService userService;

@PropertySource

@Component
@PropertySource(value = {"classpath:user.properties"})
public class User implements Serializable {
    private String name;
    private Integer age;

    public User(){}

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

属性

@Value()

获取配置文件中的值为属性赋值

@Value("${name}")
private String name;

使用指定的值

@Value("陈加兵")
private String name;    

表达式赋值

 @Value("#{10+22}")
 private Integer age;

@Profile

上一篇下一篇

猜你喜欢

热点阅读