-
标注在类上,表明该类是一个配置类,相当于之前写的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 开发仅需注解、开发效率起飞
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Just My Type
Simon Garfield / Profile Books / 2010-10-21 / GBP 14.99
What's your type? Suddenly everyone's obsessed with fonts. Whether you're enraged by Ikea's Verdanagate, want to know what the Beach Boys have in common with easy Jet or why it's okay to like Comic Sa......一起来看看 《Just My Type》 这本书的介绍吧!