Spring注解解析

  • @Configuration注解

该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。

@Configuration //配置类
public class MainConfig {

    //向容器注入bean  类型为返回值类型  id默认为方法名
    @Bean(value = "person")
    public Person persons() {
        return new Person("ysl",25);
    }

}

获取容器中的实例通过AnnotationConfigApplicationContext 类将配置类中的Bean加载到容器中.
通过@Autowired 和 @Resource 同理都可以获取容器中的Bean实例.

  • @ComponentScan
    该类的作用就是告诉Spring从哪里找到Bean然后进行加载.
@ComponentScan(value = {"springcode"},excludeFilters = { // 扫描的包路径  并执行排除操作
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,  //配置过滤类   指定过滤类型
                classes = {BookController.class})  //排除给定的类型   BookController类
},includeFilters = {
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
        classes = {BookController.class}) //包含给定的类型   BookController类
},useDefaultFilters = false) //useDefaultFilters  默认为true 包含必须设置为false 否则包含规则不生效
  • @ComponentScan 源码:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};  扫描包路径  返回的是String[]数组 

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;  包含加载Bean 时必须将此属性设置为false 否则包含条件不生效

    ComponentScan.Filter[] includeFilters() default {}; 包含加载的Bean

    ComponentScan.Filter[] excludeFilters() default {};  排除加载的Bean

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {  过滤接口
        FilterType type() default FilterType.ANNOTATION;   过滤类型   默认注解类型

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};  过滤class

        String[] pattern() default {};
    }
}
  • @Scope 注解:
    该注解作用是用于容器中的Bean设置作用域.
    value 属性:
    prototype :多实例 每次获取对象实例时将Bean注册到容器中.
    singleton: 单实例 (默认值) 容器启动时将Bean注册到容器中.
  • @Lazy 注解:
    该注解用于控制Bean注册容器的时机,容器启动时不加载获取实例时进行加载(一次),称之为懒加载.
  • @Conditional 注解:
    该注解始于spring4.X 开始,SpringBoot 底层大量使用,按照条件进行判断,满足条件将Bean注册容器中.(也可以放在类上)
@Conditional(value = {WindowsCondition.class})
    @Bean(value = "Bill Gates")
    public Person personTo() {
        System.out.println("Bill Gates");
        return new Person("Bill Gates",49);
    }

    @Conditional(value = {LinuxCondition.class})
    @Bean(value = "Linus")
    public Person personThree() {
        System.out.println("Linus");
        return new Person("Linus",50);
    }
public class LinuxCondition implements Condition {

    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取BeanFactory工厂
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取系统资源
        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Linux")) {
            return true;
        }
        return false;
    }
}
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取BeanFactory工厂
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取系统资源
        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows")) {
            return true;
        }
        return false;
    }
}

以上代码容器中注入的两个Bean分别加上条件过滤,但是只有一个注册成功 如图:

Spring注解忽略导出字段 spring如何解析注解_Spring注解忽略导出字段

  • @Import 注解:
    该注解作用是快速将Bean注册到容器中,id默认全类名.
    value 属性:全类名Bean注册容器或者自定义类实现ImportSelector 接口自定义需要注册的Bean或者实现ImportBeanDefinitionRegistrar接口自定义注册Bean.

注册Bean的方式:

  • xml文件注册
  • @Configuration+@Bean
  • @Import
    1.实现ImportSelector接口自定义注册Bean
    2.实现ImportBeanDefinitionRegistrar接口自定义注册Bean
  • 通过FactoryBean接口注册Bean

Bean 生命周期:

  • @Bean(initMethod = “init”,destroyMethod = “destroy”) 注解:
public class A {


    public A() {
        System.out.println("A 构造...");
    }

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

    public void destroy() { // AnnotationConfigApplication.close 关闭容器    开始销毁
        System.out.println("A 销毁...");
    }

}
@Bean(initMethod = "init",destroyMethod = "destroy")  //自定义Bean的初始化方法和销毁方法(构造方法在之前执行)
    public A a() { 
        return new A();
    }

注意:如使用@Scope(“prototype”) 多实例的话,容器启动时不会进行初始化操作只用在获取Bean时才进行初始化还有就是调用close方法Bean的实例不会自动销毁(手动调用可以销毁).

  • Bean实现InitializingBean(初始化)和DisposableBean(销毁)接口:
public class B implements InitializingBean,DisposableBean {

//同理都可以控制Bean的生命周期.
    public B() {
        System.out.println("B 构造...");
    }

    @Override
    public void afterPropertiesSet() throws Exception { //初始化
        System.out.println("B init...");
    }

    @Override
    public void destroy() throws Exception { //销毁
        System.out.println("B destroy...");
    }
}
  • @PostConstruct和@PreDestroy注解:
@Component
public class C {

    public C() {
        System.out.println("C 构造..");
    }

    //对象创建并赋值之后进行初始化
    @PostConstruct
    public void init() {
        System.out.println("C init...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("C destroy...");
    }

}
  • BeanPostProcessor 接口:
/**
 * 后置处理器:Bean初始化前后进行包装工作    Spring底层使用此接口实现Bean注册工作
 */
@Component
public class D implements BeanPostProcessor {


    //Bean初始化之前进行操作
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization"+beanName+"==>"+bean);
        return bean;
    }

    //Bean初始化之后进行操作
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization"+beanName+"==>"+bean);
        return bean;
    }
}
  • @Value注解:
/**
     * @Value 属性赋值
     * 1.基本数值
     * 2.spel: #{}
     * 3.${} 配置文件中的值
     */
    @Value("张三")
    private String name;

    @Value("#{20-2}")
    private Integer age;

	@Value("${person.nikeName}") //配置文件中根据K拿到V
    private String nikeName;

public void profile1(@Value("${bird.name}")String name) {}  

还可以通过接口EmbeddedValueResolverAware 重写setEmbeddedValueResolver方法来获取resolver.resolveStringValue("${bird.nikename}") 配置文件中的值
//@PropertySource 读取外部配置文件中的K/V保存到运行环境变量中
@PropertySource(value = {"classpath:/person.properties"})
@Configuration
public class MainConfigOfProperty {
    @Bean
    public Person person() {
        return new Person();
    }
}
  • @Autowired注解:spring
@Qualifier("bookDao2") //指定装备组件
    @Autowired(required = false) // 容器中Bean不存在不抛异常   
    private BookDao bookDao2;
  • @Resource和@Inject注解:java
  • @Resource(name="") 容器中的bean组件必须存在

同上注解作用一样都是注入,这两个注解时jdk的默认按照名字注入,而Autowired注解是Spring (强大)默认按照类型注入。

  • @Profile 注解:用于方法 或者 类上
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
 context.getEnvironment().setActiveProfiles(“test”,“dev”); //设置需要激活的环境
 context.register(MainConfigProfile.class); //注册配置
 context.refresh(); //刷新容器

该注解作用用于判断系统环境来注册不同的Bean组件。