Spring注解

目录

AnnotaionConfigApplicationContext

@AliasFor

@Configuration

@ComponentScan

@Component

@Bean

@Scope

@Lazy

@Conditional

@Import

@AutoWired

@Qualifier

@Primary

@Resource

@Inject

@PropertySource

@Value

@Profile


AnnotaionConfigApplicationContext

指定配置类生成IOC容器

@Test
    public void test1(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        User user = applicationContext.getBean("user1", User.class);
        System.out.println(user);
    }

@AliasFor

 设置别名,用于为注解属性声明别名

spring-@AliasFor注解_Just-Today的博客-优快云博客

@Configuration

表示标记该注解的类是一个spring配置类,可代替xml配置文件

@ComponentScan

指定扫描组件所在的包

参考【Spring注解】@ComponentScan之includeFilters和excludeFilters_小白伐的博客-优快云博客

public enum FilterType {
    //根据注解类型过滤
	ANNOTATION,

    //根据指定类的类型过滤
	ASSIGNABLE_TYPE,

	//ASPECTJ表达式
	ASPECTJ,

	//正则表达式
	REGEX,

	//自定义过滤规则,TypeFilter接口实现类
	CUSTOM
}
@Configuration
@ComponentScan(basePackages = "com.mzp.component",useDefaultFilters = false,
                includeFilters = {
                    //@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
                    //@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {TestConfig.class}),
                    @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {TestCustomFilter.class})
                })
public class Config {
    @Bean()
    public User getUser(){
        return new User("user1", 11);
    }
}
public class TestCustomFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println(classMetadata.getClassName());
        return true;
    }
}

@Component

标明某个类是Spring的Bean,需要Spring容器进行管理

指定id

@Component("id")

@Repository、@Controller、@Service与@Component作用一样,底层也使用了@Component注解

@Bean

在配置类中标记该注解的方法的返回值对象将会由spring容器进行管理,名称默认是方法名,类型是返回值类型,可通过@Bean的value指定名称

@Bean("beanUser")
    public User getUser(){
        return new User("jack");
    }

@Scope

设置bean作用域,默认是singleton(单例模式)

/*
        singleton:单例,ioc容器创建时调用方法创建该对象放到ioc容器
        prototype:多实例,ioc容器创建时不会创建该对象,每次获取该对象时才会调用方法创建对象
        request:同一个request请求创建一个实例
        session:同一个session请求创建一个实例
     */
    @Scope("prototype")
    @Bean()
    public User getUser(){
        return new User("user1", 11);
    }

@Lazy

懒加载,在单例模式下,ioc容器创建时并不会立刻调用方法创建对象,而是在第一次调用(获取)时调用方法创建对象并放到ioc容器中

@Lazy
@Bean()
public User getUser(){
        System.out.println("创建user");
        return new User("user1", 11);
    }

@Conditional

满足特定条件后,将bean注册到ioc容器中

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

	Class<? extends Condition>[] value();

}

通过实现Condition接口来自定义条件

public class WindowCondition implements Condition {
    /**
     *
     * @param context 上下文
     * @param metadata 相关类或方法上的注解信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Window")){
            return true;
        }
        //System.out.println(metadata);
        return false;
    }
}
@Conditional(WindowCondition.class)//注解在类上,满足特定条件后,将该bean对象注册到ioc容器中
@Configuration
@ComponentScan("com.mzp.component.config")
public class TestConditional {
    @Bean
    public User getUser2(){
        return new User("user2", 1);
    }
    @Bean("windowUser")
    public User getUser(){
        return new User("window", 1);
    }

    @Bean("linuxUser")
    @Conditional(LinuxCondition.class)//注解在方法上,满足条件后,将方法返回值注册到ioc容器中
    public User getUser1() {
        return new User("linux", 1);
    }
}

@Import

快速给容器中导入组件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
	 * or regular component classes to import.
	 */
    //组件的class、ImportSelector、ImportBeanDefinitionRegistrar的实现类
	Class<?>[] value();

}

@Import({Blue.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyImportSelector implements ImportSelector {
    /**
     *
     * @param importingClassMetadata 当前标识Import注解的类的所有注解信息
     * @return 返回组件的全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.mzp.component.service.Red"};
    }
}
public class  MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata 标识Import注解的类的所有注解信息
     * @param registry Bean定义的注册类
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //定义bean,例如该bean的作用域
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
        registry.registerBeanDefinition("rain",rootBeanDefinition);
    }
}

@AutoWired

默认按照属性类型注入。

若是有多个相同类型,则以属性名称为id注入属性,若是以属性名称为id找不到相同名称id的bean组件,则报错。

可通过设置required属性为false,获取不到对应bean组件,不报错

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

@Autowired可使用在构造器、方法、参数、属性、注解定义类上

注意:注入规则跟在属性上一致,默认按照类型注入,多个相同类型则按参数id注入

1、构造器

标记在有参构造器上,则参数会从IOC容器中根据类型获取并赋值到对应参数。

若是只有一个有参构造器,则可省略@Autowird注解。

注意

a)构造器上的参数需要从容器中获取,若是获取不到,则报错,可通过@Autowired里的required属性设置false,则获取不到,不报错。

b)参数需为引用类型

@Component
public class Color {
    @Autowired
    public Color(Red red){
        this.red2 = red;
    }
    private Red red2;

    public Red getRed2() {
        return red2;
    }

    public void setRed2(Red red2) {
        this.red2 = red2;
    }

}

2、方法

package com.mzp.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Color {
    private Red red2;

    public Red getRed2() {
        return red2;
    }

    @Autowired
    @Qualifier("red")
    public void setRed2(Red red1) {
        this.red2 = red1;
    }

}

标记@Bean的方法的参数,参数从容器中获取,@Autowired可省略

@Bean
    public Red red(@Autowired Dog dog){
        return new Red();
    }

3、参数

标记在参数上,只能标记在构造器或@Bean注解方法上才有效,若是只有一个有参构造器,也可省略注解

注意

a)构造器上的参数需要从容器中获取,若是获取不到,则报错,可通过@Autowired里的required属性设置false,则获取不到,不报错。

b)参数需为引用类型

package com.mzp.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Color {
    public Color(Red red, Red red1, @Autowired(required = false)@Qualifier("t")Red t){
        System.out.println(red);
        System.out.println(red1);
    }
    private Red red2;
    public Red getRed2() {
        return red2;
    }
    public void setRed2(Red red1) {
        this.red2 = red1;
    }

}

4、属性

package com.mzp.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Color {
    @Autowired
    @Qualifier("red1")
    private Red red2;

    public Red getRed2() {
        return red2;
    }

    public void setRed2(Red red2) {
        this.red2 = red2;
    }

}

@Qualifier

与@AutoWired注解配合使用,可用该注解指定id

@Primary

可在对应bean加上该注解,则使用@Autowired进行自动装配时,若有多个相同类型的组件,则优先将标识@Primary注解的组件注入属性中(若使用@Qualifier则会注入指定名称id的组件)

注意:同一类型只能标识其中一个组件,否则报错

@Resource

该注解是Java注解。

默认根据属性名称为id注入属性,可通过指定name来指定id注入属性

package com.mzp.bean;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;


@Component
public class Color {
    @Resource(name = "red1")
    private Red red;
    public Red getRed() {
        return red;
    }
    public void setRed(Red red) {
        this.red = red;
    }

}

@Inject

@inject注解是Java注解,使用需引入依赖。

<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

功能与@Autowired功能一致,少了required属性功能。可与spring@Qualifier、@Primary注解配套使用。

package com.mzp.bean;

import org.springframework.stereotype.Component;

import javax.inject.Inject;

@Component
public class Color {
    @Inject
    private Red red;
    public Red getRed() {
        return red;
    }
    public void setRed2(Red red) {
        this.red = red;
    }

}

@PropertySource

将指定配置文件加载到容器中

可通过IOC容器的environment属性获取对应配置文件key-value值或者@Value注解获取

SpringIOC容器中BeanPostProcessor后置处理器处理标识该注解,将配置文件解析配置到容器中。

可参考:spring-bean生命周期_Just-Today的博客-优快云博客

package com.mzp.component.config;

import com.baomidou.mybatisplus.extension.api.R;
import com.mzp.bean.Red;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan({"com.mzp.bean"})
@PropertySource(name="test",value = {"classpath:/test.properties"})
public class ConfigurationAutowired {
    @Bean
    public Red red(){
        return new Red();
    }

    @Bean
    public Red red1(){
        return new Red();
    }
}
 @Test
    public void test9(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationAutowired.class);
        
        String property = applicationContext.getEnvironment().getProperty("test.name");
        System.out.println(property);
    }

@Value

单一属性注入值

1、普通类型

@Value("11")
    private String value;

2、SpEl表达式,通过@Value("#{表达式}")

@Value("#{11*11}")
    private String value;

3、从IOC配置文件中获取对应值,通过@Value("${key}"),若是找不到,则直接将${key}字符串返回

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

@Profile

 @Profile可根据当前环境,动态激活或切换一系列组件的功能,也就是根据@Profile的value参数判断当前环境是否符合并加载该组件到IOC容器中。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {

	/**
	 * The set of profiles for which the annotated component should be registered.
	 */
	String[] value();

}

例如在开发环境、测试环境、生产环境下加载不同组件。

若标记在类上,则符合环境后,该类组件和内部相关配置才会被加载到容器中。

若是不指定环境标识,默认是default环境,则default默认被加载到容器中。

没有指定@Profile环境标识的bean组件,任何环境都可被加载。

package com.mzp.component.config;

import com.baomidou.mybatisplus.extension.api.R;
import com.mzp.bean.Dog;
import com.mzp.bean.Red;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan({"com.mzp.bean"})
@PropertySource(name="test",value = {"test.properties"})
public class ConfigurationAutowired {
    @Bean("test")
    @Profile({"test"})
    public Red red(){
        return new Red();
    }

    @Bean("dev")
    @Profile("dev")
    public Red red1(){
        return new Red();
    }

    @Bean("default")
    @Profile("default")//若是不指定环境标识,默认是default环境,则default默认被加载到容器中
    public Red red2(){
        return new Red();
    }
}

 1、在容器刷新之前设置好环境

@Test
    public void test9(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.getEnvironment().setActiveProfiles("test");
        applicationContext.register(ConfigurationAutowired.class);
        applicationContext.refresh();


        for (String s : applicationContext.getBeanNamesForType(Red.class)) {
            System.out.println(s);
        }

    }

2、通过命令行参数设置环境

@Test
    public void test9(){

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationAutowired.class);

        for (String s : applicationContext.getBeanNamesForType(Red.class)) {
            System.out.println(s);
        }

    }

-Dspring.profiles.active=dev

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值