关于注解1

一.注解的定义

所有定义的注解都默认实现了Annotation接口,就像所有的类都默认继承了Object类,定义的注解至少有2个注解用于指定注解的可使用的范围和运行范围

类或方法等使用注解,被正常调用时是没有任何作用的,只有被反射调用时,才会发挥作用(反射针对注解做了处理)

@Override注解

@Taeget注解 指定 注解可以使用的 位置

METHOD可用于方法上
PARAMETER可用于参数上
CONSTRUCTOR可用于构造方法上
LOCAL_VARIABLE可用于局部变量上
ANNOTATION_TYPE可用于注解类型上(被interface修饰的类型)
PACKAGE用于记录java文件的package信息
ANNOTATION_TYPE可用于注解类型上(被interface修饰的类型)

@Retention(RetentionPolicy.RUNTIME) 必须指定 运行范围   RUNTIME(这个才会被反射获取到)

 

二.注解的使用

springboot最核心的注解: 

@SpringBootApplication = (默认属性)@Configuration 
                       + @EnableAutoConfiguration
                       + @ComponentScan.

@Configuration 用于定义配置类,可替换XML配置文件,被注解的类内部包含一个或多个@Bean注解方法

@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为在Spring应用程序上下文中的bean。

@EnableAutoConfiguration:能够自动配置spring的上下文,试图猜测和配置你想要的bean类,通常会自动根据你的类路径和你的bean定义自动配置。

@ComponentScan:会自动扫描指定包下的全部标有@Component的类,并注册成bean,当然包括@Component下的子注解@Service,@Repository,@Controller

二.@Component 和 @Bean 是两种使用注解来定义bean的方式

@Component声明性的。负责创建实例(也就是bean)并存入IOC容器,  @Autowired取出实例注入到引用上

web开发,提供3个取代@Component注解的衍生注解(功能一样,都是创建bean,放入容器)
        @Repository(“名称”):dao层
        @Service(“名称”):service层
        @Controller(“名称”):web层

        @service注解本身就承担了两个职责:
        一是Bean的创建;可用@Component 代替
        二是将一个类标识为一个服务。

         @Component注解默认实例化的对象是单例,如果想声明成多例对象可以使用 

                @Component
                @Scope("prototype")

        @Repository默认单例 (待验证)

        @Service默认单例 (待验证)

        @Controller默认多例 (待验证)


@Bean用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。(@Bean 比较方便的声明一个对象,)

@Configuration 加后被spring管理 单例模式 @Configuration是单例

@Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。比如当引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现

 三.@Resource与@Autowired

1.   @Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired。

     @Resource注解由J2EE提供,需要导入包javax.annotation.Resource

2.@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入

@Autowired是根据类型进行自动装配的。如果当Spring上下文中存在不止一个UserDao类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在UserDao类型的bean,

也会抛出BeanCreationException异常。我们可以使用@Qualifier配合@Autowired来解决这些问题 

@Qualifier告诉spring具体去装配哪个对象

四. @Value注解使用

通常使用第一种方式@Value(“${}”)读取配置文件的值(application.properties或application.yml)

代码

配置文件

第二种 @Value("#{}")  Spring 表达式语言(简称SpEL)


五.@PostConstruct

被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次

Constructor > @Autowired > @PostConstruct

//------------------------------------------------------------------------------------------------------------------

六. @Around
  • 可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;
  • 可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法 通常需要在线程安全的环境下使用
  • <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

//------------------------------------------------------------------------------------------------------------------

@ConditionalOnProperty来控制Configuration是否生效

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

    String[] value() default {}; //数组,获取对应property名称的值,与name不可同时使用  
  
    String prefix() default "";//property名称的前缀,可有可无  
  
    String[] name() default {};//数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用  
  
    String havingValue() default "";//可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置  
  
    boolean matchIfMissing() default false;//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错  
  
    boolean relaxedNames() default true;//是否可以松散匹配,至今不知道怎么使用的  
} 
}

//在application.properties配置    framework.swagger.enable=true

通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值。
如果该值为空,则返回false;
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。

@Configuration
//在application.properties配置"framework.swagger.enable",对应的值为true
@ConditionalOnProperty(prefix="framework.swagger",name = "enable", havingValue = "true")
public class SwaggerConfig {
    @Autowired
    private HelloServiceProperties helloServiceProperties;
    @Bean
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        helloService.setMsg(helloServiceProperties.getMsg());
        return helloService;
    }
}

//------------------------------------------------------------------------------------------------------------------

@ConfigurationProperties("jwt")

//------------------------------------------------------------------------------------------------------------------

自定义注解:

//------------------------------------------------------------------------------

spring.factories 优先加载实例

Spring Factories实现原理

spring-core包里定义了SpringFactoriesLoader类,这个类实现了检索META-INF/spring.factories文件,并获取指定接口的配置的功能。在这个类中定义了两个对外的方法:

loadFactories 根据接口类获取其实现类的实例,这个方法返回的是对象列表。
loadFactoryNames 根据接口获取其接口类的名称,这个方法返回的是类名的列表。
上面的两个方法的关键都是从指定的ClassLoader中获取spring.factories文件,并解析得到类名列表,具体代码如下

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }

        try {
            Enumeration<URL> urls = (classLoader != null ?
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            result = new LinkedMultiValueMap<>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    String factoryClassName = ((String) entry.getKey()).trim();
                    for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                        result.add(factoryClassName, factoryName.trim());
                    }
                }
            }
            cache.put(classLoader, result);
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }

从代码中我们可以知道,在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。也就是说我们可以在自己的jar中配置spring.factories文件,不会影响到其它地方的配置,也不会被别人的配置覆盖。

spring.factories的是通过Properties解析得到的,所以我们在写文件中的内容都是安装下面这种方式配置的:

com.xxx.interface=com.xxx.classname

在日常工作中,我们可能需要实现一些SDK或者Spring Boot Starter给被人使用时,
我们就可以使用Factories机制。Factories机制可以让SDK或者Starter的使用只需要很少或者不需要进行配置,只需要在服务中引入我们的jar包即可


 

spring注解的作用:

//----------------------------------------------------------------

@Documented 

在自定义注解的时候可以使用@Documented来进行标注,如果使用@Documented标注了,在生成javadoc的时候就会把@Documented注解给显示出来。

要牢记,只要用到注解,必然有三角关系:

  • 定义注解
  • 使用注解
  • 读取注解

仅仅完成前两步,是没什么卵用的。就好比你写了一本武林秘籍却没人去学,那么这门武功还不如一把菜刀.

注解的读取并不只有反射一种途径.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值