Spring常用注解

@Configuration

        声明当前类是一个配置类(相当于一个Spring配置的xml文件)

        @Configuration不可以是final类型;

        @Configuration不可以是匿名类; 

        嵌套的configuration必须是静态类。

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

@ComponentScan

  • 自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加入spring容器
  • 通过includeFilters加入扫描路径下没有以上注解的类加入spring容器
  • 通过excludeFilters过滤出不用加入spring容器的类
  • 自定义增加了@Component注解的注解方式
package com.org.config;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan(value = "com.org.ums.controller")
public class BeanConfig {

}

@ComponentScans

        可包含多个@ComponentScan
        示例:@ComponentScans(value =         {@ComponentScan,@ComponentScan,@ComponentScan})

@ComponentScans({
        @ComponentScan(basePackages = {
                "com.org.sxd.controller"
        }, includeFilters = {
                // 仅仅使用了 @RestController 注解声明的类
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { RestController.class })
        }, useDefaultFilters = false),
        @ComponentScan(basePackages = {
                "com.org.springboot.controller2"
        }, excludeFilters = {
                // 过滤使用了 @MyAnnotation 注解的类
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { MyAnnotation.class })
        })
})
public class MyConfig {

}

@Lazy

        实际开发过程中并不是所有的bean都需要一开始就被创建,有些我们可以在使用的时候进行创建,此时可以使用@Lazy实现懒加载。

        单实例bean:默认在容器启动的时候创建对象;
        懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

        @Lazy注解作用于类上时,通常与@Component及其衍生注解配合使用。
        @Lazy注解作用于方法上时,通常与@Bean注解配合使用。

//@Lazy与@component配合使用
@Component
@Lazy

public class UserService {

    
    public UserService(){
        System.out.println("userService创建了");
    }
}


@Configuration
@ComponentScan(basePackages = "lazyDemo")
public class SpringConfig {

    @Bean
    @Lazy
    // @Lazy与@Bean注解配合使用
    public UserService userService1(){
        return new UserService();
    }
}

public class TestLazyDemo {

    private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

    @Test
    public void testLazyDemo() throws SQLException {


        System.out.println("容器初始化完成");
        UserService userService = (UserService) context.getBean("userService");
        UserService userService1 = (UserService) context.getBean("userService1");

    }
}


@Conditional

        它的逻辑语义可以作为"If…then…else…"来对bean的注册起作用。

        SpringBoot 模块大量的使用@Conditional 注释,我们可以将Spring的@Conditional注解用于以下场景:

  • 可以作为类级别的注解直接或者间接的与@Component相关联,包括@Configuration类;
  • 可以作为元注解,用于自动编写构造性注解;
  • 作为方法级别的注解,作用在任何@Bean方法上。

        Condition接口

        ​ 我们需要一个类实现Spring提供的Condition接口,它会匹配@Conditional所符合的方法,然后我们可以使用我们在@Conditional注解中定义的类来检查。

public class MqttCondition implements Condition {
    @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            System.out.println("MqttCondition。。。。");
            //1、能获取到ioc使用的beanfactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //2、获取类加载器
            ClassLoader classLoader = context.getClassLoader();
            //3、获取当前环境信息
            Environment environment = context.getEnvironment();
            String isOpen = environment.getProperty("mqtt.isOpen");
            return Boolean.valueOf(isOpen);
    }
}
@Configuration
public class MqttConfig {
 
    @Autowired
    private MqttAcceptClient mqttAcceptClient;
 
    @Conditional(MqttCondition.class)
    @Bean
    public MqttAcceptClient getMqttAcceptClient(){
 
        mqttAcceptClient.connect();
        //mqttAcceptClient.subscribe("test_queue",0);
        return mqttAcceptClient;
    }
}

        @Conditional 注解可以作用在类上,表示此类下面所有的bean满足条件后都可以进行注入,通常与@Configuration注解一起使用。

        上图满足MqttCondition.class的matches方法为true的时候注入相应的Bean。

@Value

        该注解的作用是将我们配置文件的属性读出来,有@Value(“${}”)@Value(“#{}”)两种方式。

        区别:@Value(“${}”)注入的为配置文件的内容,@Value(“#{}”)则为SpEL表达式对应的内容。 那个default_value,就是前面的值为空时的默认值。注意二者的不同,#{}里面那个obj代表对象。

@Getter
@Setter
@Component
@Configuration
public class MqttConfiguration {

    @Value("${spring.mqtt.broker}")
    private String host;

    @Value("${spring.mqtt.clientId}")
    private String clientId;

    @Value("${spring.mqtt.username}")
    private String username;

    @Value("${spring.mqtt.password}")
    private String password;

    @Value("${spring.mqtt.timeout}")
    private int timeout;

    @Value("${spring.mqtt.KeepAlive}")
    private int KeepAlive;

    @Value("${spring.mqtt.topics}")
    private String topics;

    @Value("${spring.mqtt.isOpen}")
    private Boolean isOpen;

    @Value("${spring.mqtt.qos}")
    private int qos;

}
spring:
  mqtt:
    broker: tcp://192.168.0.168:1883
    clientId: mqtt_client #客户端的id
    username: admin
    password: public
    timeout: 2000
    KeepAlive: 20
    topics: test_queue #主题
    qos: 1 #心跳包级别
    isOpen: true

        @Value(“#{}”)在使用的时候我们需要准备一个实体类并注入到Bean当中,再通过@Value(“#{}”)去获取相应的属性值。

 这里需要注意一点: 

        最好将配置文件交给sping加载,不要交给springMVC加载 避免出现错误,因为web.xml配置时spring的监听先启动,springMVC的Dispatcherservlet接收到请求时初始化springMVC的配置文件。

@Autowired

        默认按类型装配,找不到或者找到多个则报错。如果要按名称装配,需要结合Spring另外一个注解Qualifier("name")使用。默认必须装配requred=true,如果可以为空,可以设置为false,在Spring4+结合jdk8+的情况下还可以使用Optional和false同等的效果,如:

@Autowired

private Optional<UserService> userService;

        需要注意的是@Autowired用在service上,但是实际注入的是实现类,通过bytype的方式进行装配。

        这里顺便简单说一下@Resource和@Inject作为了解。虽然他们不是spring的注解

      **@Resource可以根据name和type进行装配

      **@Inject和@Autowired差不多,可以实现完全替代,没有required属性,而且必须有bean存在。如果使用byname装配方式则要搭配@Named注解使用

@Scope

        @Scope注解是springIoc容器中的一个作用域,在 Spring IoC 容器中具有以下几种作用域:基本作用域singleton(单例)prototype(多例),Web 作用域(reqeust、session、globalsession),自定义作用域。

  • singleton单例模式(默认):全局有且仅有一个实例
  • prototype原型模式:每次获取Bean的时候会有一个新的实例
  • request: request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前http request内有效
  • session :session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前http session内有效
  • global session : global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义

直接使用字符串容易出问题,spring有默认的参数:

  • ConfigurableBeanFactory.SCOPE_PROTOTYPE,即“prototype”
  • ConfigurableBeanFactory.SCOPE_SINGLETON,即“singleton”
  • WebApplicationContext.SCOPE_REQUEST,即“request”
  • WebApplicationContext.SCOPE_SESSION,即“session”

使用方法:

        @Scope直接加在bean对象方法上,如:

/**
* 定义一个bean对象
* @return
*/
@Scope    //@Scope(value = "prototype")
@Bean(value = "user0", name = "user0", initMethod = "initUser", destroyMethod = "destroyUser")
public User getUser() {
    System.out.println("创建user实例");
    return new User("张三", 18);
}

        大多数业务中使用singleton就可以了,感觉这也是为啥他默认设置为单例类型的原因,singleton保证了全局是一个实例,但是如果实例为非静态变量的时候,会导致线程安全的问题。

        当设置为类型为prototype的时候,每次连接请求,都会生成一个bean实例,也会导致一个问题,当请求数越多,性能会降低,因为创建的实例,导致GC频繁,gc时长会增加。

        直接在controller上设置多例是正常的,但是如果在controller层调用service层,其中controller层是默认的单例的话,service层设置多例会导致多例失效。因为:

        虽然Service是多例的,但是Controller是单例的。如果给一个组件加上@Scope("prototype")注解,每次请求它的实例,spring的确会给返回一个新的。问题是这个多例对象Service是被单例对象Controller依赖的。而单例服务Controller初始化的时候,多例对象Service就已经注入了;当你去使用Controller的时候,Service也不会被再次创建了(注入时创建,而注入只有一次)。

@Profile

       可以实现不同环境(开发、测试、部署等)使用不同的配置。

        在spring使用DI来依赖注入的时候,能够根据当前制定的运行环境来注入相应的bean。最常见的就是使用不同的DataSource。

        当我们指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

  • 1)加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
  • 2)写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
  • 3)没有标注环境标识的bean,在任何环境下都是加载的;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那山川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值