Spring框架新注解与最佳实践
- 发布时间:2025-04-24 09:35:37
- 本文热度:浏览 117 赞 0 评论 0
- 文章标签: Spring Framework Bean作用域 条件注解
- 全文共1字,阅读约需1分钟
Bean作用域注解
@Scope注解深度解析
@Scope注解用于定义Bean的作用范围,是Spring容器管理Bean生命周期的重要机制。在Spring 5.x版本中,作用域类型扩展到六种:
- singleton(默认)
- prototype
- request
- session
- application
- websocket
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
}
原型模式Bean的创建流程:
- 容器初始化时不创建实例
- 每次getBean()调用时
- 调用BeanPostProcessor的postProcessBeforeInitialization
- 执行@PostConstruct方法
- 调用InitializingBean的afterPropertiesSet
- 调用自定义init-method
- BeanPostProcessor的postProcessAfterInitialization
作用域代理模式
当短生命周期作用域Bean注入长生命周期Bean时,必须使用代理:
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public UserPreferences userPreferences() {
return new UserPreferences();
}
代理模式 | 适用场景 | 实现原理 |
---|---|---|
TARGET_CLASS | 类代理 | CGLIB动态代理 |
INTERFACES | 接口代理 | JDK动态代理 |
NO | 默认值 | 不创建代理 |
延迟加载机制
@Lazy注解实现原理
@Configuration
public class LazyConfig {
@Bean
@Lazy
public HeavyResource heavyResource() {
System.out.println("HeavyResource初始化...");
return new HeavyResource();
}
}
延迟加载的触发时机:
- ApplicationContext.getBean()
- @Autowired自动注入
- 通过ObjectProvider获取
延迟加载与代理模式
Spring通过动态代理实现延迟加载机制,核心逻辑位于LazyScope:
public class LazyScope implements Scope {
public Object get(String name, ObjectFactory<?> objectFactory) {
return new LazyObjectProxy(objectFactory);
}
private static class LazyObjectProxy implements Serializable {
private final ObjectFactory<?> objectFactory;
private volatile Object target;
public Object get() {
if (target == null) {
synchronized (this) {
if (target == null) {
target = objectFactory.getObject();
}
}
}
return target;
}
}
}
条件化配置注解
@Conditional底层架构
条件注解的核心接口:
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
Spring内置条件实现类:
- OnClassCondition
- OnBeanCondition
- OnWebApplicationCondition
- OnPropertyCondition
自定义条件实现
实现操作系统判断条件:
public class OScondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String os = env.getProperty("os.name");
return os != null && os.contains("Windows");
}
}
组合条件配置示例:
@Configuration
public class SystemConfig {
@Bean
@Conditional(WindowsCondition.class)
public CommandService windowsCmd() {
return new WindowsCommandService();
}
@Bean
@Conditional(LinuxCondition.class)
public CommandService linuxCmd() {
return new LinuxCommandService();
}
}
环境配置注解
@Profile实现原理
Spring 4.0之后@Profile基于@Conditional实现:
@Retention(RetentionPolicy.RUNTIME)
@Conditional(ProfileCondition.class)
public @interface Profile {
String[] value();
}
class ProfileCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
Environment env = context.getEnvironment();
for (Object value : attrs.get("value")) {
if (env.acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
多环境配置示例:
# application-dev.properties
spring.datasource.url=jdbc:mysql://dev-db:3306/test
# application-prod.properties
spring.datasource.url=jdbc:mysql://prod-db:3306/prod
激活方式:
- spring.profiles.active=dev
- JVM参数:-Dspring.profiles.active=prod
- 环境变量:export SPRING_PROFILES_ACTIVE=dev
依赖处理注解
@DependsOn高级用法
解决初始化顺序问题:
@Configuration
public class InitSequenceConfig {
@Bean
@DependsOn({"cacheManager", "configLoader"})
public ServiceCoordinator serviceCoordinator() {
return new ServiceCoordinator();
}
@Bean
public CacheManager cacheManager() {
return new EhCacheManager();
}
@Bean
public ConfigLoader configLoader() {
return new RemoteConfigLoader();
}
}
初始化顺序控制流程:
- configLoader实例化
- cacheManager实例化
- serviceCoordinator实例化
- configLoader初始化方法执行
- cacheManager初始化方法执行
- serviceCoordinator初始化方法执行
自动装配注解
@Primary与@Qualifier
解决自动装配歧义性:
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource mainDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Qualifier("backup")
public DataSource backupDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://backup-db:3306/backup")
.build();
}
}
@Service
public class DataService {
@Autowired
private DataSource primaryDataSource;
@Autowired
@Qualifier("backup")
private DataSource backupDataSource;
}
装配优先级:
- @Qualifier指定名称
- @Primary标注的Bean
- 变量名称匹配Bean名称
- 类型唯一Bean
注解性能优化
注解处理优化策略
- 使用@Indexed加速组件扫描
@Indexed
@Component
public class FastComponent {}
- 合理配置@ComponentScan
@Configuration
@ComponentScan(
basePackages = "com.example.main",
excludeFilters = @Filter(type = FilterType.REGEX,
pattern = "com.example.test.*")
)
public class OptimizedScanConfig {}
- 启用Lite模式
@Configuration(proxyBeanMethods = false)
public class LiteModeConfig {
@Bean
public ServiceBean serviceBean() {
return new ServiceBean(repositoryBean());
}
@Bean
public RepositoryBean repositoryBean() {
return new RepositoryBean();
}
}
性能对比测试数据:
配置方式 | 启动时间 | 内存占用 |
---|---|---|
全注解模式 | 3200ms | 480MB |
Lite模式 | 2100ms | 320MB |
XML配置 | 2800ms | 410MB |
注解安全实践
敏感配置加密
结合@Value与解密处理器:
@Configuration
public class SecureConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfig() {
PropertySourcesPlaceholderConfigurer configurer
= new PropertySourcesPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource("secure.properties"));
configurer.setPropertyResolver(new EncryptedPropertyResolver());
return configurer;
}
@Service
public class SecureService {
@Value("${db.password}")
private String dbPassword;
}
}
自定义属性解析器:
public class EncryptedPropertyResolver implements PropertyResolver {
private static final String ENC_PREFIX = "ENC(";
private static final String ENC_SUFFIX = ")";
@Override
public String getProperty(String key) {
String value = // 原始属性获取
if (value.startsWith(ENC_PREFIX) && value.endsWith(ENC_SUFFIX)) {
return decrypt(value.substring(4, value.length()-1));
}
return value;
}
private String decrypt(String ciphertext) {
// AES解密实现
}
}
注解调试技巧
注解元数据追踪
查看注解的元数据信息:
public class AnnotationDebugger implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String name : beanNames) {
BeanDefinition definition = beanFactory.getBeanDefinition(name);
if (definition.getSource() instanceof AnnotatedTypeMetadata) {
AnnotatedTypeMetadata metadata = (AnnotatedTypeMetadata) definition.getSource();
Set<String> annTypes = metadata.getAnnotationTypes();
annTypes.forEach(annType -> {
Map<String, Object> attrs = metadata.getAnnotationAttributes(annType);
System.out.println("Bean: " + name);
System.out.println("Annotation: " + annType);
System.out.println("Attributes: " + attrs);
});
}
}
}
}
调试输出示例:
Bean: dataSource
Annotation: org.springframework.context.annotation.Primary
Attributes: {value=true}
Bean: taskScheduler
Annotation: org.springframework.scheduling.annotation.EnableScheduling
Attributes: {}
正文到此结束
相关文章
热门推荐
评论插件初始化中...