-
标注在类上,表明该类是一个配置类,相当于之前写的spring的xml文件,通常与
@Bean
结合使用 -
该注解同时拥有了
@Component
的作用,将当前类注入ioc容器-
其中有一个
value
属性,指定注入ioc容器的名称,默认是类名首字母小写 -
源码如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration {}
-
其中有一个
@Bean
- 在配置类中使用该注解
-
标注在方法上,默认将方法的返回对象注入到ioc容器,名称默认使用的是方法名
/** * 配置类 */ @Configuration(value = "MyConfiguration") public class MyConfiguration{ /** * 注入一个User对象,ioc容器中的name是user,类型是User类型 */ @Bean public User user(){ return new User(1,"name"); } }
属性
-
name
:指定注入ioc容器中的名称 -
value
:同name -
autowireCandidate
:是否能够自动注入,默认是true,如果指定了属性为false,那么不能使用@Autowired
或者@Resource
自动注入 -
initMethod
:指定初始化方法,在构造方法之后执行 -
destroyMethod
:指定销毁方法,在容器关闭的时候执行
实例
/** * 配置类 */ @Configuration(value = "MyConfiguration") public class MyConfiguration{ /** * 注入一个User对象,ioc容器中的name是user,类型是User类型 * init是User类中的init方法,destory是User类中的destory方法 */ @Bean(initMethod = "init",destroyMethod = "destory") public User user1(){ return new User(1,"name"); } } /** * User类 */ public class Userimplements Serializable{ private Integer id; private String name; public User(String name){ this.name = name; } public User(Integer id, String name){ System.out.println("执行构造方法"); this.id = id; this.name = name; } public void init(){ System.out.println("初始化方法"); } public void destory(){ System.out.println("销毁方法"); } }
@Scope
- 指定对象的作用域名,标注在类上或者方法上,默认是单实例
四大作用域
singleton prototype request session
/** * 指定多实例,每次用到都会调用 */ @Bean(initMethod = "init",destroyMethod = "destory") @Scope(value = "prototype") public User user1(){ return new User(1,"name"); }
@Conditional
- 标注在方法或者在类上,只有在满足其中的匹配条件才会将对象注入到ioc容器中。
-
只有一个属性value,是一个
Condition
数组,要向实现相应的功能,可以自定义一个类,实现Condition
这个接口即可。 -
这个注解在SpringBoot中将会有很多的扩展,这里就不多说了。
/** * 指定多实例,每次用到都会调用 * @Conditional 只有里面全部都匹配才会正常注入到容器中 */ @Bean(initMethod = "init",destroyMethod = "destory") @Conditional(value = {FirstCondition.class}) public User user1(){ return new User(1,"name"); }
-
下面看看
FirstCondition
这个类具体实现-
只需要实现接口中的
matches
方法即可,返回true表示符合条件,否则不满足条件,只有满足条件才会注入到ioc容器中/** * 自定义的条件判断,实现Condition接口 */ public class FirstConditionimplements Condition{ /** * 如果返回true表示符合条件,反之不符合条件 * @param context ConditionContext对象,可以获取上下文的信息 * @param metadata AnnotatedTypeMetadata对象,可以获取标注在该方法上面的注解信息 * @return */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){ //获取Environment,用来获取运行环境中的一些变量 Environment environment = context.getEnvironment(); //获取在properties文件中配置的参数,表示是否注入相关属性 Boolean isAutowired = environment.<Boolean>getProperty("isAutowired", Boolean.class); return isAutowired; } }
-
只需要实现接口中的
ConditionContext
-
主要的功能是获取上下文的对象,比如BeanFactory
public interface ConditionContext{ /** * 获取 BeanDefinitionRegistry,可以自己手动注册对象到ioc容器中 */ BeanDefinitionRegistrygetRegistry(); /** * 获取BeanFacotory,操作ioc容器,比如获取对应的Bean,判断ioc中是否已经注入 */ @Nullable ConfigurableListableBeanFactorygetBeanFactory(); /** * 返回当前的运行环境,可以获取运行环境中的一下参数,或者一些配置文件中的数据 */ EnvironmentgetEnvironment(); /** * 获取资源加载器 */ ResourceLoadergetResourceLoader(); /** * 获取类加载器 */ @Nullable ClassLoadergetClassLoader(); }
AnnotatedTypeMetadata
-
主要的作用就是获取标注了
@Conditional
这个注解的方法上的注解和对应的参数等信息public interface AnnotatedTypeMetadata{ /** * 判断方法上是否有对应的注解 * @param annotationName 注解类的全类名,getName() */ boolean isAnnotated(String annotationName); /** * 获取对应注解的全部属性的值,key是属性,value是属性的值 * @param annotationName 注解类的全类名,getName() */ @Nullable Map<String, Object>getAnnotationAttributes(String annotationName); @Nullable Map<String, Object>getAnnotationAttributes(String annotationName,boolean classValuesAsString); @Nullable MultiValueMap<String, Object>getAllAnnotationAttributes(String annotationName); @Nullable MultiValueMap<String, Object>getAllAnnotationAttributes(String annotationName,boolean classValuesAsString); }
@PostConstruct
-
标注在方法上,用来在类加载并且属性赋值之后调用,通常用来初始化,和
@Bean
中的init-menthd
指定的作用相同@PostConstruct public void init(){ System.out.println("初始化方法"); }
@PreDestroy
-
标注在方法上,容器销毁执行,相当于
@Bean
中的destroy-method
属性@PreDestroy public void destory(){ System.out.println("销毁方法"); }
@Import
-
用来形式化的注入,主要形式有:
- 直接导入类
- 导入配置类
- 指定ImportSelector
- 使用ImportBeanDefinitionRegistrar手动注册
直接导入类
-
直接在
value
属性中指定需要导入的类即可,如下:@Configuration(value = "MyConfiguration") @Import(value = {Person.class}) public class MyConfiguration{}
导入配置类
-
新建一个配置类,但是不用
@Configuration
标注,使用@Import
在另外一个配置类上引入即可/** * 这是一个配置,但是并没有使用@Configuration这个注解,因此不会生效 */ public class SecondConfiguration{ @Bean public Person person(){ return new Person(); } }
-
在另外一个配置类使用
@Import
注解引入上面的配置类,如下:@Configuration(value = "MyConfiguration") @Import(value = {SecondConfiguration.class}) public class MyConfiguration{}
指定ImportSelector
-
使用ImportSelector需要自定义一个实现类,如下:
/** * 自定义Selector,需要实现ImportSelector */ public class FirstSelectorimplements ImportSelector{ /** * 筛选逻辑,返回的是String数组(需要注入到容器中的类的全类名) * @param importingClassMetadata AnnotationMetadata对象,对标注了@Import这个注解的类中的所有注解信息,比如获取标注指定注解的方法 * @return 返回的是需要注入的字符串数组(类的全类名) */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //获取@Import标注的类中被@Bean标注的方法元数据 Set<MethodMetadata> annotatedMethods = importingClassMetadata.getAnnotatedMethods(Bean.class.getName()); annotatedMethods.forEach(o->{ System.out.println(o.getMethodName()); }); //将Person类返回去,那么将会自动注入Person return new String[]{Person.class.getName()}; } }
-
在配置类上使用
@Import
注解引入即可,如下:@Configuration @Import(value = {FirstSelector.class}) public class MyConfiguration{}
AnnotationMetadata
public interface AnnotationMetadataextends ClassMetadata,AnnotatedTypeMetadata{ //拿到Class上标注的所有注解,依赖于Class#getAnnotations Set<String>getAnnotationTypes(); // 拿到所有的元注解信息AnnotatedElementUtils#getMetaAnnotationTypes //annotationName:注解类型的全类名 Set<String>getMetaAnnotationTypes(String annotationName); // 是否包含指定注解 (annotationName:全类名) boolean hasAnnotation(String annotationName); //这个厉害了,依赖于AnnotatedElementUtils#hasMetaAnnotationTypes boolean hasMetaAnnotation(String metaAnnotationName); // 类里面只有有一个方法标注有指定注解,就返回true //getDeclaredMethods获得所有方法, AnnotatedElementUtils.isAnnotated是否标注有指定注解 boolean hasAnnotatedMethods(String annotationName); // 注意返回的是MethodMetadata 原理基本同上 // .getDeclaredMethods和AnnotatedElementUtils.isAnnotated 最后吧Method转为MethodMetadata Set<MethodMetadata>getAnnotatedMethods(String annotationName); }
使用ImportBeanDefinitionRegistrar手动注册
-
需要自定义一个类实现
ImportBeanDefinitionRegistrar
,如下:/** * 自定义的FirstBeanDefinitionRegistrar,需要实现ImportBeanDefinitionRegistrar */ public class FirstBeanDefinitionRegistrarimplements ImportBeanDefinitionRegistrar{ /** * 自己手动注册Bean到ioc容器中 * @param importingClassMetadata 获取@Import标注的类上的注解信息,比如获取被指定注解标注的方法信息 * @param registry 注册中心,可以获取指定bean的信息和手动注册bean */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){ //如果容器中没有Person这个Bean,就创建一个 if (!registry.containsBeanDefinition(Person.class.getName())){ GenericBeanDefinition beanDefinition=new GenericBeanDefinition(); beanDefinition.setBeanClass(Person.class); //手动注册 registry.registerBeanDefinition("person",beanDefinition); } } }
-
在配置类上使用
@Import
注解引入即可,如下:@Configuration @Import(value = {FirstBeanDefinitionRegistrar.class}) public class MyConfiguration{}
@Primary
- 在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。
-
有两种使用方式,一种是结合
@Bean
,另外一种是结合@Service,@Component,@Controller.....
@Bean @Primary public User user1(){ return new User(1,"user1"); } //第二种 @Primary @Component public class Person{ private String name; private Integer age; }
@Autowired
- 标注在方法和属性上,用来自动为成员变量赋值
-
默认先根据属性的类型从ioc容器中查找,如果ioc容器中存在多个类型相同的属性,将会根据 变量名
从ioc容器中查找。
@Controller public class UserController{ @Autowired private UserService userService;
属性
-
required
:指定该属性是否是必须的,默认为true,表示一定要为属性赋值,如果ioc容器中没有对应的Bean,那个将会报错,如果为false,会先从ioc容器中查找对应的Bean,如果存在就进行赋值,不存在就不赋值,不会报错。
@Qualifier
-
和
@Autowired
结合使用,用来从容器中注入指定名字的Bean -
使用场景:容器中存在多个类型相同的Bean,那么此时仅仅使用
@Autowired
就不太适用了,此时就要结合该注解,指定需要注入的name。(当然除了@Autowired
还是可以根据成员变量的名称进行注入的)@Controller public class UserController{ @Autowired @Qualifier(value = "userService") private UserService userService;
@PropertySource
-
从配置文件中读取相关配置注入到指定的成员属性中
@Component @PropertySource(value = {"classpath:user.properties"}) public class Userimplements Serializable{ private String name; private Integer age; public User(){} public User(String name, Integer age){ this.name = name; this.age = age; }
属性
value ignoreResourceNotFound
@Value()
-
有三个典型的使用场景:
- 获取配置文件中对应的值,为指定属性赋值
- 使用指定的值为属性赋值
- 通过表达式计算得到的值为属性赋值
获取配置文件中的值为属性赋值
-
使用
${}
的方式获取配置文件中设置的值@Value("${name}") private String name;
使用指定的值
-
其中的
value
属性可以是自己随便指定的值,如下:@Value("陈加兵") private String name;
以上所述就是小编给大家介绍的《Spring注解开发》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- springmvc教程--注解开发基础详解
- SpringMVC入门学习---使用注解开发
- Erupt 1.6.1 发布,全注解式开发,通用后台管理框架,提供全栈注解级解决方案
- Erupt 1.6.3 发布,注解式开发全行业管理后台,提供全栈注解级解决方案
- 「Android」Android开发你需要知道的注解(Annotation)
- Erupt 1.7.1 发布,国产、零前端代码、ADMIN 开发仅需注解、开发效率起飞
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。