注解详解

java基础注解

@FunctionallInterface

高阶函数:如果一个函数接收一个函数作为参数,或者返回一个函数作为返回值,那么该函数就叫做高阶函数。函数式编程语言js等语言里面都支持大量的高阶函数,JAVA从1.8开始也开始支持高阶函数。

此接口作用与只有一个抽象方法的接口上(接口是抽象类的变体),但是接口并不继承Object类

//TODO

 

@link

使用一场景:当某些方法被@Deprecated注解并有替换方法,可以在替换方法上使用,语法如下

/**
*@Deprecated in favor of
{link #copy_reference}//替换方法的全reference
*
*/
@Deprecated   
public void xxx();//被替换方法

public void substrute_xxx();

这样其他程序员在使用过时方法的时候,就可以通过idea发现替换方法。

 

@see

//TODO

 

Rest 相关注解

Rest相关的注解如下

@QueryParam   @BeanParam @PathParam @ApplicationParam

springframework注解

pring框架功能很强大,但是就算是一个很简单的项目,我们也要配置很多东西。因此就有了Spring Boot框架,它的作用很简单,就是帮我们自动配置。Spring Boot框架的核心就是自动配置,只要存在相应的jar包,Spring就帮我们自动配置。如果默认配置不能满足需求,我们还可以替换掉自动配置类,使用我们自己的配置。另外,Spring Boot还集成了嵌入式的Web服务器,系统监控等很多有用的功能,让我们快速构建企业及应用程序。

Springboot的注解包括多种注解

@RequestBody

@Bean,@Component,@Controller,@Service, @Repository,

@Configuration,@EnableAutoConfiguration,@ComponentScan,@SpringbootApplicatiion

@ResponseBody,@RestController 

@Import,@ImportResource,@Resource,@Qualifier

@AutoWired,@Value,@Inject,@Autowired,@Scope,@PostConstruct,@PreDestory

@RunWith,@SpringBootTest,@ConfigurationProperties,@PropertySource,@ContextConfiguration

1 Bean注解详解

@Bean是一个方法级别的注解,主要用在@Configuration注解的类中,也可以用在@Component注解的类中,添加的bean的id默认为方法名。

@Configuration

public class AppConfig {

    @Bean

    public TransferService transferService() {

        return new TransferServiceImpl();

    }

}

这个配置就等同于之前在xml里的配置

<beans>

    <bean id="transferService" class="com.acme.TransferServiceImpl"/>

</beans>

bean的依赖

 

@bean 也可以依赖其他任意数量的bean,如果TransferService 依赖 AccountRepository,我们可以通过方法参数实现这个依赖

 

@Configuration

public class AppConfig {

    @Bean

    public TransferService transferService(AccountRepository accountRepository) {

        return new TransferServiceImpl(accountRepository);

    }

 

}

@PostConstruct, @PreDestory

接受生命周期的回调

 @PostConstruct说明

         被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。

执行顺序

@ PostConstruct注释用于在完成依赖项注入以执行任何初始化之后需要执行的方法。必须在类投入使用之前调用此方法。 所有支持依赖注入的类都必须支持此注释。即使类没有请求注入任何资源,也必须调用使用PostConstruct注释的方法。 只有一个方法可以使用此批注进行批注。 应用PostConstruct注释的方法必须满足以下所有条件:除了拦截器之外,方法绝不能有任何参数,在这种情况下它采用Interceptor规范定义的InvocationContext对象。 在拦截器类上定义的方法必须具有以下签名之一: void <METHOD>(InvocationContext)Object <METHOD>(InvocationContext)抛出异常注意: PostConstruct拦截器方法不能抛出应用程序异常,但可以声明它抛出检查异常,包括java.lang.Exception, 如果相同的拦截器方法除了生命周期事件之外插入业务或超时方法。 如果PostConstruct拦截器方法返回一个值,容器将忽略它。 在非拦截器类上定义的方法必须具有以下签名:void <METHOD>()应用PostConstruct的方法可以是public,protected,package private或private。 除应用程序客户端外,该方法绝不能是静态的。 该方法可能是最终的。如果该方法抛出一个未经检查的异常,那么该类绝不能投入使用,除非EJB可以处理异常甚至从它们恢复的EJB   然后就会思考问题,这个注释是修饰初始化之后需要执行的方法,那么它和@Autowired、构造函数的执行顺序是什么呢?(当然注释中已经说明了PostConstruct注释用于在完成依赖项注入之后)

@Service

public class BeanA {

 

    @Autowired

    private BeanB beanB;

 

    public BeanA() {

        System.out.println("这是Bean A 的构造方法");

    }

 

 

    @PostConstruct

    private void init() {

        System.out.println("这是BeanA的 init 方法");

        beanB.testB();

    }

}

@Service

public class BeanB {

 

    @PostConstruct

    private void init() {

        System.out.println("这是BeanB 的init 方法");

    }

 

    public BeanB() {

        System.out.println("这是Bean B的 构造方法");

    }

 

    void testB() {

        System.out.println("这是Bean B 的 testB 方法");

    }

}

 

 

启动后输出: 

这是Bean A 的构造方法

这是Bean B的 构造方法

这是BeanB 的init 方法

这是BeanA的 init 方法

这是Bean B 的 testB 方法

所以得到结论: 构造方法 > @Autowired > @PostConstruct

 

 

 @PreConstruct说明

         被@PreConstruct修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreConstruct修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

 

任何使用@Bean定义的bean,也可以执行生命周期的回调函数,类似@PostConstruct and @PreDestroy的方法。用法如下

public class Foo {

    public void init() {

        // initialization logic

    }

}

public class Bar {

    public void cleanup() {

        // destruction logic

    }

}

@Configuration

public class AppConfig {

    @Bean(initMethod = "init")

    public Foo foo() {

        return new Foo();

    }

    @Bean(destroyMethod = "cleanup")

    public Bar bar() {

        return new Bar();

    }

}

默认使用javaConfig配置的bean,如果存在close或者shutdown方法,则在bean销毁时会自动执行该方法,如果你不想执行该方法,则添加@Bean(destroyMethod="")来防止出发销毁方法

 

指定bean的scope,使用@Scope注解

你能够使用@Scope注解来指定使用@Bean定义的bean

 

@Configuration

public class MyConfiguration {

 

    @Bean

    @Scope("prototype")

    public Encryptor encryptor() {

        // ...

    }

bean的别名,默认情况下bean的名称和方法名称相同,你也可以使用name属性来指定

@Configuration

public class AppConfig {

 

    @Bean(name = "myFoo")

    public Foo foo() {

        return new Foo();

    }

 

}

bean的命名支持别名,使用方法如下

@Configuration

public class AppConfig {

    @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })

    public DataSource dataSource() {

        // instantiate, configure and return DataSource bean...

    }

 

}

bean的描述

 

有时候提供bean的详细信息也是很有用的,bean的描述可以使用 @Description来提供

 

@Configuration

public class AppConfig {

    @Bean

    @Description("Provides a basic example of a bean")

    public Foo foo() {

        return new Foo();

    }

 

}

 

@Resource注解

 

@Component详解

Component是一个元注解,意味着他可以注解其他类注解,如@Controller,@Service, @Repository以及@Aspect, 官方的原话是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化。其他类级别的注解也可以被认定为是一种特殊类型的组件,比如@Repository @Aspect所以,@Component可以注解其他类注解。

Component名称

a.不指定bean的名称,默认为类名首字母小写university

@Component

public class University {

          to do sthing...

}

获取bean方式:

ApplicationContext ctx  = new ClassPathXmlApplicationContext("./config/application Context.xml");

           University ust = (University) ctx.getBean("university");

 

b.指定bean的名称

@Component("university1")

public class University {

          to do sthing...

}

获取bean方式:

ApplicationContext ctx  = new ClassPathXmlApplicationContext("./config/applicationContext. xml");

           University ust = (University) ctx.getBean("university1");

@Component和@Bean的区别

众所周知,@Component注解是在Spring 2.5版本引入的,以便于可以通过路径扫描的方式来替换配置文件。@Bean是在Spring3.0版本引入的,可以配合使用@Configuration注解来达到完全替换配置文件的目的。同时@Bean是一个方法注解,而@Component是一个类注解。@Component和@Bean做两个完全不同的事情,不应该混为一谈。

在 @Component 注解的类中不能定义(类内依赖@Bean注解的)这种方法。@Configuration可以。

Spring帮助我们管理Bean分为两个部分,一个是注册Bean,一个装配Bean
完成这两个动作有三种方式,一种是使用自动配置的方式、一种是使用JavaConfig的方式,一种就是使用XML配置的方式。
在自动配置的方式中,使用@Component去告诉Spring,我是一个bean,你要来管理我,然后使用@AutoWired注解去装配Bean(所谓装配,就是管理对象直接的协作关系)。然后在JavaConfig中,@Configuration其实就是告诉spring,spring容器要怎么配置(怎么去注册bean,怎么去处理bean之间的关系(装配))。那么久很好理解了,@Bean的意思就是,我要获取这个bean的时候,你spring要按照这种方式去帮我获取到这个bean。到了使用xml的方式,也是如此。君不见<bean>标签就是告诉spring怎么获取这个bean,各种<ref>就是手动的配置bean之间的关系。

@Configuration

@Configuration注解一般注解在类里面有@Value注解的成员变量或@Bean注解的方法,@Bean主要和@Configuration配合使用的。@Configuration注解本质上还是一个@Compoent,因此<context:component-scan/>或者@ComponenScan都能处理@Configuration注解的类

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component

public @interface Configuration {

    String value() default "";

}

可以看到在@Configuration注解中是包含@Component注解的,被@Configuration修饰的类被定义为一个Spring容器(应用上下文)

@Configuration就相当于Spring配置文件中的<beans />标签,里面可以配置bean。

@Configuration标注的类必须符合下面所有要求:

  • 配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)。
  • 配置类不能是 final 类(没法动态代理)。
  • 配置注解通常为了通过 @Bean 注解生成 Spring 容器管理的类。
  • 配置类必须是非本地的(即不能在方法中声明,不能是 private)。
  • 任何嵌套配置类都必须声明为static。
  • @Bean方法不能创建进一步的配置类(也就是返回的bean如果带有@Configuration,也不会被特殊处理,只会作为普通的 bean)。

Spring 容器在启动时,会加载默认的一些PostPRocessor,其中就有 ConfigurationClassPostProcessor,这个后置处理程序专门处理带有@Configuration注解的类,这个程序会在bean定义加载完成后,在bean初始化前进行处理。其主要处理的过程就是使用 cglib 动态代理对类进行增强,使用增强后的类替换了beanFactory原有的 beanClass,增强类会对其中带有@Bean注解的方法进行额外处理,确保调用带@Bean注解的方法返回的都是同一个实例。

但是对于@Component,@Component 注解并没有通过cglib来代理@Bean方法的调用,因此调用带@Bean注解的方法态返回的都是新的实例。

读取配置文件

一般我们配置配置文件都是多套的,测试环境test,生产环境prod,开发环境dev,xx环境stage,不同的环境下某些参数是不一样的,因而配置文件也会不一样的。

注意配置文件命名规范:application-xxx.yml因为项目默认加载配置文件时会有这个格式要求:1springboot默认使用一个全局的配置文件,配置文件名是固定的,配置文件有两种(开头都是application,主要是文件的后缀):Application.properties和application.yml

配置完文件放在src/main/resource目录或者类路径/config下

application.yml,application-dev.yml,application-test.yml,application-stage.yml文件

在application.yml配置文件中一般配置的都是公共的不用动的配置

Server:

         Port:8090//不写则默认8080

Spring:

         Profiles:

                  Active:stage

其他配置文件内容:

application-dev.yml

spring:

    profiles: dev

user:

    userName: 王立国-dev

    sex: 男

    age: 18

author:

    name: wlg-dev

    height: 174

application-test.yml

spring:

    profiles: test

user:

    userName: 王立国-test

    sex: 男

    age: 18

author:

    name: wlg-test

height: 174

 

application-stage.yml

spring:

    profiles: stage

 

user:

    userName: 王立国-stage

    sex: 男

    age: 18

author:

    name: wlg-stage

    height: 174

每个配置文件都说明了自己的spring.profiles名称,然后其他内容稍有不同以示区分。

 

读取配置文件的方式有两种:@PropertySouce和@ImportSource

@PropertySource

1、@PropertySource配置文件路径设置,加载指定的配置文件,在类上添加注解,如果在默认路径下可以不添加该注解。注意@PropertySource只能加载.properties文件而不能加载.yml文件

需要用@PropertySource的有:

  • 例如非application.properties,classpath:config/my.properties指的是src/main/resources目录下config目录下的my.properties文件,
  • 例如有多配置文件引用,若取两个配置文件中有相同属性名的值,则取值为最后一个配置文件中的值
  • 在application.properties中的文件,直接使用@Value读取即可,applicarion的读取优先级最高

@PropertySource({"classpath:config/my.properties","classpath:config/config.properties"})

public class TestController

@ImportSource

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上

@Import

在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解,注意@Import只能使用在类上。

@Import 有三种使用方式

1,直接填写class数组

2,实现ImportSelector

3,ImportBeanDefinitionRegistrar方式

示例如下: 先创建两个类,不用注解注入到IOC容器中,在应用的时候在导入到当前容器中。 

1、创建Dog和Cat

package com.example.demo;

public class Dog { }

cat类

package com.example.demo;

public class Cat {}

 

2、在启动类中需要获取Dog和Cat对应的bean,需要用注解@Import注解把Dog和Cat的bean注入到当前容器中。

package com.example.demo;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Import;

 

//@SpringBootApplication

@ComponentScan

/*把用到的资源导入到当前容器中*/

@Import({Dog.class, Cat.class})  //这样就会把dog和cat实例放入到spring容器中

public class App {

 

    public static void main(String[] args) throws Exception {

 

        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);

        System.out.println(context.getBean(Dog.class));

        System.out.println(context.getBean(Cat.class));

        context.close();

    }

}

3、运行该启动类,输出结果:

com.example.demo.Dog@4802796d

com.example.demo.Cat@34123d65

从输出结果知,@Import注解把用到的bean导入到了当前容器中。并且id为默认全类名,而@Bean只是类型

 

第二种

public class MyImportSelector implements ImportSelector{


    @Override
    
    public String[] selectImports(AnnotationMataData annotationMetaData){

        //返回值: 就是我们实际上要导入到容器中的组件全类名【重点 】
        //参数:AnnotationMetadata表示当前被@Import注解给标注的所有注解信息【不是重点】
        //需要注意的是selectImports方法可以返回空数组但是不能返回null,否则会报空指针异常!

    }
}

第三种,使用ImportBeanDefinitionRegister,只不过这种方法可以自定义注册

public class Myclass2 implements ImportBeanDefinitionRegistrar {
//该实现方法默认为空
    public class Myclass2 implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, 
BeanDefinitionRegistry beanDefinitionRegistry) {
        //指定bean定义信息(包括bean的类型、作用域...)
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);
        //注册一个bean指定bean名字(id)
        beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);
    }
}
}

 

另外,也可以导入一个配置类

还是上面的Dog和Cat类,现在在一个配置类中进行配置bean,然后在需要的时候,只需要导入这个配置就可以了,最后输出结果相同。

 

MyConfig 配置类:

 

package com.example.demo;

import org.springframework.context.annotation.Bean;

 

public class MyConfig {

 

    @Bean

    public Dog getDog(){

        return new Dog();

    }

 

    @Bean

    public Cat getCat(){

        return new Cat();

    }

 

}

比如若在启动类中要获取Dog和Cat的bean,如下使用:

 

package com.example.demo;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Import;

 

//@SpringBootApplication

@ComponentScan

/*导入配置类就可以了*/

@Import(MyConfig.class)

public class App {

 

    public static void main(String[] args) throws Exception {

 

        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);

        System.out.println(context.getBean(Dog.class));

        System.out.println(context.getBean(Cat.class));

        context.close();

    }

}

@Value详解

利用@Value获取值,在springboot中如果不配置@PropertySource(value="classpath:redis.properties")(配置文件路径),默认是从application.properties中获取值,你也可以配置额外的@PropertySource,如下:

 

@Value("${my.name}")

private String myName;

3、实例

我在application-test.properties里面加上属性wechat.pay.url

@Primary

配置在某个接口有多个实现类的某个实现类上,在其他Bean中使用@Autowired注入该接口类型的bean时,优先注入这个实现类的bean。和@Component一起使用,否则无效。

@ConfigurationProperties

为springboot 专用的属性注入属性 ,文件名必须是application.properties/applicaiton.yml 默认为全局文件中获取这些属性值 。@ConfigurationProperties告诉spring波特将本类中的所有属性和配置文件中相关的配置进行绑定,prefix=”person”:配置文件中下面的的属性进行一一映射。

例如:

//将配置文件中的每一个属性的值映射到这个组件中

//告诉springboot将本类中的所有属性和配置文件中的相关配置进行绑定

//(prefix = "person")将配置文件中以person下的所有属性进行绑定

@Component

@ConfigurationProperties(prefix = "person")

public class Person {

    private  String name;

    private  Integer age;

    private boolean boss;//布尔值

    private Date bir;//时间

 

    private Map<String,Object> map;//Map

    private List<String> lists;//List

 

    private Dog dog;//对象

}

public class Dog {

    private String name;

    private  Integer age;

}

在yml配置文件中

person:

  name: Mr

  age: 14

  boss: true

  bir: 2018/12/21

  map: {m1: v1,m2: v2}

  lists:

     - mc

     - mt

  dog:

     name: dogdog

     age: 10

 使用properties后缀的:

person.name=mr

person.age=22

person.bir=2018/12/11

person.boss=true

person.map.q1=1

person.map.q2=2

person.lists=a,b,c

person.dog.name=cat

person.dog.age=22

@ComponentScan

@Component是标注哪个类被扫描进入spring IOC容器中,而@ComponentScan是表明采用何种策略去扫描装配bean。默认情况下,@ComponentScan只会扫描当前包和子包。

 

@Condition和@Conditional

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)

@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)

@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)

@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)

@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)

@ConditionalOnNotWebApplication(不是web应用)

uploading.4e448015.gif转存失败重新上传取消

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值