1.10.5. Defining Bean Metadata within Components
@Component
public class FactoryMethodComponent {
private static int i;
@Bean
@Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
// use of a custom qualifier and autowiring of method parameters
@Bean
protected TestBean protectedInstance(
@Qualifier("public") TestBean spouse,
@Value("#{privateInstance.age}") String country) {
TestBean tb = new TestBean("protectedInstance", 1);
tb.setSpouse(spouse);
tb.setCountry(country);
return tb;
}
@Bean
private TestBean privateInstance() {
return new TestBean("privateInstance", i++);
}
@Bean
@RequestScope
public TestBean requestScopedInstance() {
return new TestBean("requestScopedInstance", 3);
}
}
上述代码向Spring Container中注册了TestBean的bean定义,可以使用@Qualifier和@RequestScope约束bean的功能,同时还在工厂方法protectedInstance中通过传参的方式支持自动装配其他的bean,并且通过@Qualifier和@Value注解约束了其功能,"#{privateInstance.age}"代表privateInstance单例对象中的age字段作为参数进行装配。
A Spring Expression Language element defines the value of the property through the notation #{ <expression> }
@Bean注解在@Component中和@Configuration中注解的方法的调用方式是不同的。@Component注解的类不会通过CGLIB进行代理,而@Configuration注解的类会通过CGLIB进行代理。
1.10.6. Naming Autodetected Components
@Component, @Repository, @Service, and @Controller支持指定bean name。示例如下:
@Service("myMovieLister")
public class SimpleMovieLister {
// ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
默认的bean name命名是驼峰式命名,由类名生成。Spring支持篡改它自身的命名规则,通过如下方式:
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
...
}
MyNameGenerator继承自BeanNameGenerator接口。
xml定义方式如下:
<beans>
<context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator" />
</beans>
一般情况下,使用Spring默认命名规则已经足够。
1.10.7. Providing a Scope for Autodetected Components
Scope使用:
@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
注意事项:
@Scope annotations are only introspected on the concrete bean class (for annotated components) or the factory method (for @Bean methods)
Sping支持自定义scope解析器:
@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {
...
}
<beans>
<context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResolver"/>
</beans>
支持配置bean的代理模式,全局配置:
@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {
...
}
<beans>
<context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
</beans>
1.10.8. Providing Qualifier Metadata with Annotations
针对候选人配置@Qualifier注解:
@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {
// ...
}
@Component
@Genre("Action")
public class ActionMovieCatalog implements MovieCatalog {
// ...
}
@Component
@Offline
public class CachingMovieCatalog implements MovieCatalog {
// ...
}
1.10.9. Generating an Index of Candidate Components
基于注解的配置需要扫描classpath来查找相应的bean定义等信息,可以通过是生成Index of Candidate Components提前生成相关信息,从而避免扫描,加快Spring应用的启动速度。
具体方法是引入如下包:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.1.5.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
编译过后会生成META-INF/spring.components:
#
#Sun Feb 24 22:17:27 CST 2019
examples.FactoryMethodComponent=org.springframework.stereotype.Component
examples.ComponentExample=org.springframework.stereotype.Component
examples.SessionScopedUserService=org.springframework.stereotype.Component
examples.AppConfig=org.springframework.stereotype.Component
examples.SimpleMovieLister=org.springframework.stereotype.Component
examples.SessionScopedService=org.springframework.stereotype.Component
examples.JpaMovieFinder=org.springframework.stereotype.Component
网友评论