spring注解小结

spring提供了一系列注解,有很多作用,此处做归纳和总结。

1. @Configuration

作用在类上,声明一个class需要被spring解析以扩充beanDefinition。@Configration注解同时被@Component注解修饰,因此具有被自动加载的特点,被@Configuration修饰的类本身也会作为definition注册。

value属性是Configuration bean名称。

2. @ComponentScan

作用在类上,声明需要对包路径下资源进行扫描,效果等同于<context:component-scan>

value(basePackages)属性指定要扫描的包路径,多个用逗号分割。

basePackageClasses属性指定class做扫描。

nameGenerator属性指定beanName命名策略。

scopeResolver属性指定从definition中解析出scope元信息的方式。

scopedProxy指定缺省的scopedProxy,决定不同scope之间的连接方式。

resourcePattern模糊匹配scan的文件。

useDefaultFilters是否使用默认的探测注解(默认探测注解含@Component和被@Component修饰的注解)

includeFilters指定includeFilter,内容是Filter对象,Filter有多种类型,且能细化多种行为,例如:

@ComponentScan(basePackages = "com.concretepage",

includeFilters = @Filter(type = FilterType.REGEX, pattern="com.concretepage.*.*Util"),

excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = IUserService.class))

excludeFilters排除的Filter。

lazyInit延迟加载。

还有ComponentScan中定义的子注解@Filter,这个注解很有意思,@Target({}),@Target里没有任何内容,意味着@Filter不用于修饰任何资源,而只是单纯的作为元信息载体。主要作为@ComponentScan的includeFilters和excludeFilters的内容,用于决定scan时过滤搜索资源的策略。@Filter有以下属性:

type(value)决定过滤器类型:

1. ANNOTATION:注解类型,配合AnnotationTypeFilter使用,筛选出被指定注解修饰的资源。

2. ASSIGNABLE_TYPE:枚举出扫描类型,配合AssignableTypeFilter使用,加载指定类型的资源(含子类)

3. ASPECTJ:用AspectJ正则方式搜索名称符合要求的资源。

4. REGEX:Java正则匹配资源。

5. CUSTOM:自定义的FIlter。

classes属性配合type使用,当type是:

1. ANNOTATION:待扫描注解

2. ASSIGNABLE_TYPE:用户枚举的类

3. CUSTOM:自定义Filter

pattern属性配合type使用,当type是:

1. ASPECTJ:ASPECTJ规范的正则内容

2. REGEX:Java规范的正则内容

@ComponentScan的解析逻辑见ConfigurationClassParser.doProcessConfigurationClass(...)

3. @PropertySource

作用在类上,加载指定路径资源到Environment,从而实现注入。

name属性指定propertySource资源名称,缺省是空,会自动生成。

value属性指定资源路径,必填,可以是"classpath:/com/myco/app.properties" or "file:/path/to/file",也可以是${...},作为变量时可以用当前所有加载到Environment里的属性做渲染。value必须指向唯一资源,不能模糊匹配到多个。

ignoreResourceNotFound,声明是否必须要找到value指定的资源,缺省false表示没有该资源时会抛错。

encoding编码。

factory属性指定封装propertySource的PropertySourceFactory,PropertySourceFactory用于将一个EncodedResource资源封装成PropertySource资源,在factory这一步可以干预PropertySource的生成。缺省用spring默认的factory。

4. @Conditional

作用在类和方法上,决定@Component(含子注解)和@Bean是否需要被加载。@Confitional的value属性是一组实现Condition接口的类,例如:

@Conditional({ ConditionTrueTest.class, ConditionTrueTest.class })

Condition接口唯一的方法是matches:

boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

入参ConditionContext是回调matcher方法时的上下文,其中包含beanFactory,environment,resourceLoader等,几乎包含了容器各方面的资源。

入参AnnotatedTypeMetadata是被该@Conditional注解修饰资源的元信息(元信息有类和方法两种,其中AnnotatedTypeMetadata是类元信息,MethodMetadata(AnnotatedTypeMetadata的子类)是方法元信息)。

当@Conditional注解有多个Condition判断条件时,多个条件之间是与的关系,也即只有所有Condition均满足条件时,才会被加载。

5. @Bean

作用在方法和注解上,作用在方法上标记此处会生成一个beanDefinition。配合Profile, Scope, Lazy, DependsOn, Primary, Order使用,描述definition行为。@Bean注解在实现上基于factory-method,因此修饰在方法上。@Bean注解本身带有name,autowire,destroyMethod,initMethod属性,充实definition。

value和name属性均指定bean名称。

autowire指定bean自动加载模式,缺省不自动加载。

initMethod指定初始化方法,等同于xml里的init-method属性,存储在definition的initMethodName变量里,缺省空。

destroyMethod指定销毁方法,同initMethod类似,等同于destroy-method。缺省值"(inferred)",意味着bean里无参的close和shutdown方法会被作为destoryMethod回调(spring称之为推断)。源码见org.springframework.beans.factory.support.DisposableBeanAdapter.inferDestroyMethodIfNecessary(...)

多说一句,被@Bean修饰的方法会作为definition的factory method,用静态或动态工厂创建bean对象。一个@Bean生成一个definition,但definition的很多属性不通过@Bean的属性来标记,而通过其它注解同样修饰在该方法上来定义。

6. @Profile

修饰类或方法,用于分类偏好(如区分环境),应用启动时决定启用哪些profile。

xml也可以指定profile,此时profile作为beans标签的一个属性,效果同@Profile。

value属性的值是字符串数组,用于存储多个profile,容器指定任意一个均可。

@Profile注解被@Conditional(ProfileCondition.class)注解修饰,因此在使用方面走的是@Conditional的判断逻辑,判断实现就是org.springframework.context.annotation.ProfileCondition,该实现在match方法里获取注解@Profile的value值,并通过Environment对象判断该profile是否被当前容器接纳,如果不被接纳,解析就终止了。

@Conditional解析在很多地方都有,例如:

org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass()

指定应用启动偏好有多种方式:

a. @ActiveProfiles注解(spring.test)

b. JVM启动参数,-Dspring.profiles.active=xxx

c. ConfigurableEnvironment.setActiveProfiles(xx),显式指定profile

d. web启动参数

<context-param>

<param-name>spring.profiles.active</param-name>

<param-value>xxx</param-value>

</context-param>

e. System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, xx);

7. @Scope

修饰类和方法,修饰类默认对类里所有bean生效,bean scope。

value和scopeName属性指定scope。

proxyMode属性指定不同scope之间的依赖绑定问题。以非单例注入单例为例,当非单例的bean注入到单例bean时,存在的主要问题是,哪一个非单例的bean应该被注入到单例bean中。 通常情况下注入单例bean的非单例bean要和当时的上下文相关,例如scope是session的bean,每次被获取到 的应该是属于当前session的bean对象。解决这个问题的方式是动态代理,单例bean里注入的是非单例bean的 代理对象,单例bean实际获取的是代理对象判断后返回的适合当前scope的实际bean对象。而proxyMode属性决定了是否要做动态代理或以何种方式动态代理。

8. @Lazy

Lazy注解作用于很广,能和很多注解配合使用,用于标记是否延迟加载。

value属性默认是true,也即带上@Lazy注解后默认就是延迟加载。

9. @DependsOn

标记是否依赖加载。

属性value的内容是字符串数据,因此一个bean能依赖多个其它bean做实例化,效果等同于xml里的depends-on。在spring做bean实例化时,如果definition中有dependsOn,则会先实例化依赖的bean。

10. @Primary

依赖注入有多个匹配项时,优先注入。

从BeanFactory中获取bean或做自动依赖注入时,可能会获得多个符合条件的对象,此时被primary修饰的对象会优先注入,但如果有两个bean都被primary修饰,就会抛错了。

11. @Order

定义顺序,值越小优先级越高,支持负数。

属性value值决定优先级,缺省是最低优先级。

12. @Import

加载一个被@Configuration修饰的class。

属性value是Class数组,因此可以注入多个值。Import注解的处理逻辑会依照Import注入class类型不同而执行不同行为:

如果被import的类是ImportSelector接口的实现类,则会回调该类实现的selectImports方法,通过返回值决定实际要import的class(实现ImportSelector接口的类未必会被import,取决于返回值)。

如果import的类是DeferredImportSelector接口的实现类,则会延迟直到所有Configuration都被解析完成后,再判断具体加载哪些class,这在使用某些Conditional条件判断里是需要的。

如果import的类是ImportBeanDefinitionRegistrar接口的实现类,则该类会被声明为一个registrar,最终在从configClass中加载definition时,向BeanFactory中注入更多definition(ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(...))。

如果以上都不满足,才会作为被@Component修饰的类来解析。

源码见org.springframework.context.annotation.ConfigurationClassParser.processImports(...)

13. @ImportResource

加载一个xml资源,和spring xml配置里import语义相同。

value和locations属性指定需要import的多个资源。

reader属性决定资源文件解析器,默认会依照文件后缀自动适配xml或groovy。

14. @Component、@Controller、@Service、@Repository、@Configuration

修饰class,自动探测时加载成bean。

value属性是组件名称。

15. @Autowired

修饰字段,方法,构造函数,入参,实现自动注入,byType。

required属性决定依赖注入是否必选,缺省true,意味着没有合适类型bean注入时,会抛出异常。

16. @Qualifier

修饰字段,方法,构造函数,入参,@Primary的精细化管理版本,通常配合@Autowired使用。

quafile相当于是给bean取了别名,缺省以beanName作为qualify。quafily定义通过xml的方式,在bean标签里写quafily标签。@Quafily注解里指定quafily名称,从而控制依赖注入的具体对象,通常配合@Autowire注解使用,使得注入方式由byType变成byName。

17. @value

修饰字段,方法,入参,实现属性注入,类型xml里的property。

同value注解相似的还有@Inject和@Autowired,这三个注解都表明属性需要被自动注入。而三个注入的统一探测逻辑在AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()方法中被探测登记,在CommonAnnotationBeanPostProcessor.postProcessPropertyValues()方法中被依赖注入。

18. @Required

修饰方法,决定是否强制注入,注解通常修饰set方法,要求set方法必须被依赖注入。

19. @Lookup

修饰方法,被修饰的方法会被动态代理重构,效果同xml中的lookup-method。

value属性的值会作为beanName从beanFactory中获取实际的bean,缺省value为空,意味着会以方法的返回类型去获取factory中的bean。

20. @Resource

javax的注解,实现自动注入,优先byName(缺省以字段名称或入参名称做搜索),其次byType。(需要CommonAnnotationBeanPostProcessor)

21. @PostConstruct

javax的注解,修饰方法,此方法会在依赖注入后回调。(需要CommonAnnotationBeanPostProcessor)

22. @PreDestroy

javax的注解,修饰方法,在对象从容器移除之前回调。(需要CommonAnnotationBeanPostProcessor)

猜你喜欢

转载自blog.csdn.net/yzb808/article/details/82588784