Spring Bean装配方式与高级特性详解

news/2025/3/23 0:31:28/文章来源:https://www.cnblogs.com/java-note/p/18787378

一、基于XML的装配

基于XML的装配是Spring最早提供的装配方式之一,它通过XML配置文件来定义Bean及其依赖关系。这种方式的优点是配置清晰、易于管理,但缺点是代码与配置分离,可能导致配置文件过于庞大和复杂。

1. 设值注入(Setter Injection)

设值注入是通过调用Bean的setter方法来注入依赖。使用这种方式时,Bean类必须提供一个无参构造方法和对应的setter方法。在XML配置文件中,使用<property>标签来指定注入的属性和值。

以下是一个简单的示例:

package com.example;public class User {private String username;private Integer password;public User() {}public void setUsername(String username) {this.username = username;}public void setPassword(Integer password) {this.password = password;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + "]";}
}

对应的XML配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.example.User"><property name="username" value="admin"/><property name="password" value="123"/></bean>
</beans>

在上述配置中,<property>标签的name属性指定了需要注入的属性名,value属性指定了注入的值。

2. 构造注入(Constructor Injection)

构造注入是通过调用Bean的构造方法来注入依赖。使用这种方式时,Bean类必须提供一个带参数的构造方法。在XML配置文件中,使用<constructor-arg>标签来指定构造方法的参数。

以下是一个构造注入的示例:

package com.example;public class User {private String username;private Integer password;public User(String username, Integer password) {this.username = username;this.password = password;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + "]";}
}

对应的XML配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.example.User"><constructor-arg name="username" value="admin"/><constructor-arg name="password" value="123"/></bean>
</beans>

在上述配置中,<constructor-arg>标签的name属性指定了构造方法的参数名,value属性指定了参数的值。

3. 集合类型的注入

Spring还支持对集合类型的注入,包括ListSetMapProperties等。以下是一个集合类型注入的示例:

package com.example;import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;public class User {private List<String> list;private Set<String> set;private Map<String, String> map;private Properties properties;public User(List<String> list, Set<String> set, Map<String, String> map, Properties properties) {this.list = list;this.set = set;this.map = map;this.properties = properties;}@Overridepublic String toString() {return "User [list=" + list + ", set=" + set + ", map=" + map + ", properties=" + properties + "]";}
}

对应的XML配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.example.User"><constructor-arg name="list"><list><value>value1</value><value>value2</value></list></constructor-arg><constructor-arg name="set"><set><value>value1</value><value>value2</value></set></constructor-arg><constructor-arg name="map"><map><entry key="key1" value="value1"/><entry key="key2" value="value2"/></map></constructor-arg><constructor-arg name="properties"><props><prop key="prop1">value1</prop><prop key="prop2">value2</prop></props></constructor-arg></bean>
</beans>

二、基于注解的装配

随着Spring框架的发展,注解(Annotation)逐渐成为一种更简洁、更灵活的Bean装配方式。注解允许开发者直接在代码中声明Bean及其依赖关系,而无需额外的XML配置文件。这种方式的优点是减少了配置文件的复杂性,同时增强了代码的可读性和可维护性。

1. 使用@Component及其衍生注解

@Component是一个通用的注解,用于标记一个类为Spring的Bean。Spring会自动扫描带有@Component注解的类,并将其注册为Bean。此外,Spring还提供了一些@Component的衍生注解,如@Service@Repository@Controller等,这些注解分别用于不同的层次,但功能与@Component类似。

以下是一个使用@Component注解的示例:

package com.example;import org.springframework.stereotype.Component;@Component
public class UserService {public void sayHello() {System.out.println("Hello from UserService!");}
}

在上述代码中,UserService类被标记为一个Spring Bean。Spring会自动扫描该类并将其注册到Spring容器中。在Spring配置文件中,需要启用注解扫描功能,如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.example"/>
</beans>

在上述配置中,<context:component-scan>标签的base-package属性指定了需要扫描的包路径。Spring会扫描指定包及其子包中的类,查找带有@Component及其衍生注解的类,并将其注册为Bean。

2. 使用@Autowired注入依赖

@Autowired注解用于自动注入依赖。Spring会根据类型匹配来查找合适的Bean,并将其注入到标记了@Autowired的字段、构造方法或setter方法中。如果存在多个匹配的Bean,Spring会根据Bean的名称(默认为类名首字母小写)进行进一步匹配。

以下是一个使用@Autowired注解的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class User {private String username;private Integer password;@Autowiredprivate UserService userService;public void display() {System.out.println("Username: " + username + ", Password: " + password);userService.sayHello();}
}

在上述代码中,userService字段被标记为@Autowired,Spring会自动注入一个UserService类型的Bean。如果Spring容器中存在多个UserService类型的Bean,Spring会根据Bean的名称进行匹配。

3. 使用@Qualifier指定注入的Bean

当存在多个相同类型的Bean时,@Autowired注解可能会导致注入失败或注入错误的Bean。此时,可以使用@Qualifier注解来指定注入的Bean的名称。

以下是一个使用@Qualifier注解的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;@Component
public class User {private String username;private Integer password;@Autowired@Qualifier("userService")private UserService userService;public void display() {System.out.println("Username: " + username + ", Password: " + password);userService.sayHello();}
}

在上述代码中,@Qualifier("userService")注解指定了注入的Bean的名称为userService。Spring会根据名称匹配来注入对应的Bean。

4. 使用@Configuration@Bean定义Bean

除了使用@Component及其衍生注解定义Bean外,还可以使用@Configuration@Bean注解来定义Bean。这种方式允许开发者在Java代码中以编程的方式定义Bean,而无需额外的XML配置文件。

以下是一个使用@Configuration@Bean注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();}
}

在上述代码中,AppConfig类被标记为@Configuration,表示它是一个配置类。userService()方法被标记为@Bean,表示它返回的对象将被注册为Spring容器中的Bean。

三、基于Java配置的装配

基于Java配置的装配是Spring 3.0引入的一种新的装配方式。它允许开发者使用Java代码来定义Bean及其依赖关系,而无需额外的XML配置文件。这种方式的优点是完全基于代码,避免了XML配置文件的复杂性,同时增强了代码的可读性和可维护性。

1. 使用@Configuration@Bean定义Bean

@Configuration注解用于标记一个类为配置类,而@Bean注解用于定义一个Bean。Spring会自动扫描带有@Configuration注解的类,并将其注册为配置类。在配置类中,可以使用@Bean注解定义多个Bean。

以下是一个使用@Configuration@Bean注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();}@Beanpublic User user() {return new User();}
}

在上述代码中,AppConfig类被标记为@Configuration,表示它是一个配置类。userService()user()方法被标记为@Bean,表示它们返回的对象将被注册为Spring容器中的Bean。

2. 使用@Import导入其他配置类

@Import注解用于导入其他配置类。当需要将多个配置类组合在一起时,可以使用@Import注解将它们导入到一个主配置类中。

以下是一个使用@Import注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@Import(AppConfig.class)
public class MainConfig {@Beanpublic MainService mainService() {return new MainService();}
}

在上述代码中,MainConfig类被标记为@Configuration,表示它是一个配置类。@Import(AppConfig.class)注解导入了AppConfig配置类,Spring会将AppConfig中的Bean注册到容器中。

3. 使用@Conditional条件装配Bean

@Conditional注解用于条件装配Bean。当满足某些条件时,Spring才会注册对应的Bean。这种方式允许开发者根据不同的环境或配置条件来动态装配Bean。

以下是一个使用@Conditional注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Bean@Conditional(WindowsCondition.class)public WindowsService windowsService() {return new WindowsService();}@Bean@Conditional(LinuxCondition.class)public LinuxService linuxService() {return new LinuxService();}
}

在上述代码中,windowsService()方法被标记为@Conditional(WindowsCondition.class),表示只有当WindowsCondition条件满足时,才会注册WindowsService Bean。linuxService()方法被标记为@Conditional(LinuxCondition.class),表示只有当LinuxCondition条件满足时,才会注册LinuxService Bean。

四、Spring Bean的生命周期

Spring Bean的生命周期是指从Bean的创建到销毁的整个过程。Spring提供了多种方式来控制Bean的生命周期,包括初始化方法和销毁方法的定义。

1. 使用@PostConstruct@PreDestroy注解

@PostConstruct注解用于定义Bean的初始化方法,而@PreDestroy注解用于定义Bean的销毁方法。Spring会在Bean创建完成后调用@PostConstruct注解的方法,而在Bean销毁之前调用@PreDestroy注解的方法。

以下是一个使用@PostConstruct@PreDestroy注解的示例:

package com.example;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;@Component
public class UserService {@PostConstructpublic void init() {System.out.println("UserService initialized");}@PreDestroypublic void destroy() {System.out.println("UserService destroyed");}public void sayHello() {System.out.println("Hello from UserService!");}
}

在上述代码中,init()方法被标记为@PostConstruct,表示它将在Bean创建完成后被调用。destroy()方法被标记为@PreDestroy,表示它将在Bean销毁之前被调用。

2. 使用InitializingBeanDisposableBean接口

InitializingBean接口和DisposableBean接口是Spring提供的另一种方式来定义Bean的生命周期方法。InitializingBean接口的afterPropertiesSet()方法用于定义Bean的初始化方法,而DisposableBean接口的destroy()方法用于定义Bean的销毁方法。

以下是一个使用InitializingBeanDisposableBean接口的示例:

package com.example;import org.springframework.stereotype.Component;@Component
public class UserService implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("UserService initialized");}@Overridepublic void destroy() throws Exception {System.out.println("UserService destroyed");}public void sayHello() {System.out.println("Hello from UserService!");}
}

在上述代码中,UserService类实现了InitializingBeanDisposableBean接口。afterPropertiesSet()方法定义了Bean的初始化逻辑,而destroy()方法定义了Bean的销毁逻辑。

五、Spring Bean的作用域

Spring Bean的作用域决定了Bean的实例化方式和生命周期。Spring提供了多种作用域,包括singletonprototyperequestsessionapplication

1. singleton作用域

singleton是Spring默认的作用域,表示Spring容器中只有一个Bean实例。无论何时请求该Bean,Spring都会返回同一个实例。

以下是一个使用singleton作用域的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class AppConfig {@Bean@Scope("singleton")public UserService userService() {return new UserService();}
}

在上述代码中,userService()方法被标记为@Scope("singleton"),表示UserService Bean的作用域为singleton。Spring容器中只会有一个UserService实例。

2. prototype作用域

prototype作用域表示每次请求该Bean时,Spring都会创建一个新的实例。这种方式适用于需要多个实例的场景。

以下是一个使用prototype作用域的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class AppConfig {@Bean@Scope("prototype")public UserService userService() {return new UserService();}
}

在上述代码中,userService()方法被标记为@Scope("prototype"),表示UserService Bean的作用域为prototype。每次请求UserService Bean时,Spring都会创建一个新的实例。

3. requestsessionapplication作用域

requestsessionapplication作用域主要用于Web应用程序中。request作用域表示每个HTTP请求都有一个独立的Bean实例;session作用域表示每个HTTP会话都有一个独立的Bean实例;application作用域表示整个Web应用程序中只有一个Bean实例。

以下是一个使用request作用域的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class AppConfig {@Bean@Scope("request")public UserService userService() {return new UserService();}
}

在上述代码中,userService()方法被标记为@Scope("request"),表示UserService Bean的作用域为request。每个HTTP请求都会有一个独立的UserService实例。

六、Spring Bean的依赖注入

依赖注入(Dependency Injection,DI)是Spring框架的核心功能之一。Spring通过依赖注入将Bean之间的依赖关系注入到Bean中,从而实现松耦合和可维护性。

1. 字段注入

字段注入是通过在字段上使用@Autowired注解来注入依赖。Spring会自动查找与字段类型匹配的Bean,并将其注入到字段中。

以下是一个字段注入的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class User {@Autowiredprivate UserService userService;public void display() {userService.sayHello();}
}

在上述代码中,userService字段被标记为@Autowired,Spring会自动注入一个UserService类型的Bean。

2. 构造方法注入

构造方法注入是通过在构造方法上使用@Autowired注解来注入依赖。Spring会调用构造方法,并将依赖注入到构造方法的参数中。

以下是一个构造方法注入的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class User {private UserService userService;@Autowiredpublic User(UserService userService) {this.userService = userService;}public void display() {userService.sayHello();}
}

在上述代码中,构造方法被标记为@Autowired,Spring会调用该构造方法,并将UserService类型的Bean注入到构造方法的参数中。

3. Setter方法注入

Setter方法注入是通过在Setter方法上使用@Autowired注解来注入依赖。Spring会调用Setter方法,并将依赖注入到Setter方法的参数中。

以下是一个Setter方法注入的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class User {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void display() {userService.sayHello();}
}

在上述代码中,setUserService()方法被标记为@Autowired,Spring会调用该方法,并将UserService类型的Bean注入到方法的参数中。

七、Spring Bean的高级特性

Spring框架提供了许多高级特性,用于进一步增强Bean的功能和灵活性。以下是一些常见的高级特性:

1. AOP(面向切面编程)

AOP是一种编程范式,用于将横切关注点(如日志记录、事务管理等)与业务逻辑分离。Spring提供了强大的AOP支持,允许开发者定义切点(Pointcut)和通知(Advice),并将其应用到Bean上。

以下是一个AOP的示例:

package com.example;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Pointcut("execution(* com.example.UserService.*(..))")public void userServiceMethods() {}@Before("userServiceMethods()")public void beforeAdvice() {System.out.println("Before method execution");}
}

在上述代码中,LoggingAspect类被标记为@Aspect@Component,表示它是一个切面类。userServiceMethods()方法定义了一个切点,匹配UserService类中的所有方法。beforeAdvice()方法定义了一个前置通知,会在匹配的方法执行之前被调用。

2. 事务管理

Spring提供了声明式事务管理功能,允许开发者通过注解或XML配置文件来定义事务规则。这种方式简化了事务管理的复杂性,同时增强了代码的可维护性。

以下是一个使用注解进行事务管理的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void createUser(User user) {userRepository.save(user);}
}

在上述代码中,createUser()方法被标记为@Transactional,表示该方法的执行需要在事务上下文中进行。Spring会自动管理事务的开始、提交和回滚。

3. 数据访问

Spring提供了多种数据访问技术,如JDBC、JPA、MyBatis等。Spring通过模板类(如JdbcTemplate)或抽象类(如JpaTemplate)封装了底层的数据访问细节,简化了数据访问代码的编写。

以下是一个使用JdbcTemplate进行数据访问的示例:

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;@Repository
public class UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;public void save(User user) {String sql = "INSERT INTO users (username, password) VALUES (?, ?)";jdbcTemplate.update(sql, user.getUsername(), user.getPassword());}
}

在上述代码中,UserRepository类被标记为@Repository,表示它是一个数据访问类。jdbcTemplate字段被标记为@Autowired,Spring会自动注入一个JdbcTemplate实例。save()方法使用JdbcTemplate执行SQL语句,将用户信息保存到数据库中。

八、Spring Bean的最佳实践

在使用Spring Bean时,遵循一些最佳实践可以帮助开发者编写更清晰、更高效、更可维护的代码。以下是一些常见的最佳实践:

1. 使用@Component及其衍生注解定义Bean

@Component及其衍生注解(如@Service@Repository@Controller)是定义Bean的首选方式。这种方式简洁明了,易于理解和维护。

2. 使用@Autowired注入依赖

@Autowired注解是注入依赖的首选方式。它允许Spring自动查找并注入依赖,减少了代码的冗余性。

3. 使用@Configuration@Bean定义复杂的Bean

当需要定义复杂的Bean或需要进行复杂的配置时,使用@Configuration@Bean注解是一种更好的选择。这种方式提供了更大的灵活性,允许开发者以编程的方式定义Bean。

4. 使用@PostConstruct@PreDestroy定义生命周期方法

@PostConstruct@PreDestroy注解是定义Bean生命周期方法的首选方式。这种方式简洁明了,易于理解和维护。

5. 使用singleton作用域

singleton是Spring默认的作用域,适用于大多数场景。只有在需要多个实例时,才考虑使用其他作用域(如prototyperequest等)。

6. 使用AOP分离横切关注点

AOP是一种强大的编程范式,可以将横切关注点(如日志记录、事务管理等)与业务逻辑分离。这种方式可以提高代码的可维护性和可扩展性。

九、Spring Bean的性能优化

在使用Spring Bean时,性能优化是一个重要的考虑因素。以下是一些常见的性能优化技巧:

1. 减少Bean的数量

过多的Bean会导致Spring容器的初始化时间变长,同时也会增加内存消耗。因此,应尽量减少不必要的Bean,只定义真正需要的Bean。

2. 使用懒加载

对于一些不需要在应用程序启动时立即初始化的Bean,可以使用懒加载(Lazy Loading)。懒加载的Bean只有在第一次被请求时才会被初始化,从而减少了Spring容器的初始化时间。

以下是一个使用懒加载的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;@Configuration
public class AppConfig {@Bean@Lazypublic UserService userService() {return new UserService();}
}

在上述代码中,userService()方法被标记为@Lazy,表示UserService Bean是懒加载的。只有在第一次请求UserService Bean时,Spring才会初始化它。

3. 使用@Cacheable缓存结果

对于一些计算成本较高且结果不经常变化的方法,可以使用@Cacheable注解来缓存结果。这种方式可以减少方法的调用次数,从而提高性能。

以下是一个使用@Cacheable注解的示例:

package com.example;import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class UserService {@Cacheable("users")public User getUserById(Long id) {// 模拟从数据库中获取用户信息return new User(id, "username");}
}

在上述代码中,getUserById()方法被标记为@Cacheable("users"),表示该方法的结果将被缓存到名为users的缓存中。如果缓存中已经存在该方法的结果,则直接返回缓存中的结果,而不需要再次调用方法。

4. 使用@Async异步执行方法

对于一些耗时较长的操作,可以使用@Async注解来异步执行方法。这种方式可以提高应用程序的响应速度,同时避免阻塞主线程。

以下是一个使用@Async注解的示例:

package com.example;import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class UserService {@Asyncpublic void sendEmail(String email) {// 模拟发送邮件System.out.println("Sending email to " + email);}
}

在上述代码中,sendEmail()方法被标记为@Async,表示该方法将异步执行。Spring会将该方法的调用提交到线程池中,而不会阻塞主线程。

十、Spring Bean的调试与监控

在使用Spring Bean时,调试和监控是确保应用程序正常运行的重要手段。Spring提供了多种工具和机制来帮助开发者进行调试和监控。

1. 使用@Profile激活特定的Bean

@Profile注解用于激活特定的Bean。通过定义不同的配置文件(如application-dev.propertiesapplication-prod.properties等),可以在不同的环境中激活不同的Bean。

以下是一个使用@Profile注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;@Configuration
public class AppConfig {@Bean@Profile("dev")public UserService userServiceDev() {return new UserService("dev");}@Bean@Profile("prod")public UserService userServiceProd() {return new UserService("prod");}
}

在上述代码中,userServiceDev()方法被标记为@Profile("dev"),表示它只在开发环境中激活。userServiceProd()方法被标记为@Profile("prod"),表示它只在生产环境中激活。

2. 使用@Conditional条件装配Bean

@Conditional注解用于条件装配Bean。通过定义自定义的条件类,可以根据不同的条件来决定是否装配某个Bean。

以下是一个使用@Conditional注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Bean@Conditional(WindowsCondition.class)public WindowsService windowsService() {return new WindowsService();}@Bean@Conditional(LinuxCondition.class)public LinuxService linuxService() {return new LinuxService();}
}

在上述代码中,windowsService()方法被标记为@Conditional(WindowsCondition.class),表示只有当WindowsCondition条件满足时,才会装配WindowsService Bean。linuxService()方法被标记为@Conditional(LinuxCondition.class),表示只有当LinuxCondition条件满足时,才会装配LinuxService Bean。

3. 使用Spring Boot Actuator监控应用程序

Spring Boot Actuator是一个用于监控和管理Spring Boot应用程序的工具。它提供了多种端点(如/actuator/health/actuator/metrics等),可以用于监控应用程序的健康状况、性能指标等。

以下是一个使用Spring Boot Actuator的示例:

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在上述代码中,@SpringBootApplication注解启用了Spring Boot Actuator。通过访问/actuator/health端点,可以获取应用程序的健康状况;通过访问/actuator/metrics端点,可以获取应用程序的性能指标。

十一、Spring Bean的高级用法

Spring框架提供了许多高级用法,用于进一步增强Bean的功能和灵活性。以下是一些常见的高级用法:

1. 使用@ConfigurationProperties绑定配置文件

@ConfigurationProperties注解用于将配置文件中的属性绑定到一个Java类中。这种方式可以简化配置文件的管理,同时提高代码的可读性和可维护性。

以下是一个使用@ConfigurationProperties注解的示例:

package com.example;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "app")
public class AppConfigProperties {private String name;private int port;// Getter and Setter methodspublic String getName() {return name;}public void setName(String name) {this.name = name;}public int getPort() {return port;}public void setPort(int port) {this.port = port;}
}

在上述代码中,AppConfigProperties类被标记为@ConfigurationProperties(prefix = "app"),表示它将绑定配置文件中以app为前缀的属性。例如,配置文件中的app.name属性将被绑定到name字段,app.port属性将被绑定到port字段。

2. 使用@Value注入配置值

@Value注解用于注入配置文件中的值。通过使用@Value注解,可以直接将配置文件中的值注入到字段或方法参数中。

以下是一个使用@Value注解的示例:

package com.example;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class UserService {@Value("${app.name}")private String appName;public void sayHello() {System.out.println("Hello from " + appName);}
}

在上述代码中,appName字段被标记为@Value("${app.name}"),表示它将注入配置文件中的app.name属性的值。

3. 使用@Primary指定首选Bean

当存在多个相同类型的Bean时,@Primary注解用于指定首选的Bean。Spring会优先注入标记为@Primary的Bean。

以下是一个使用@Primary注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;@Configuration
public class AppConfig {@Bean@Primarypublic UserService userService1() {return new UserService("Service 1");}@Beanpublic UserService userService2() {return new UserService("Service 2");}
}

在上述代码中,userService1()方法被标记为@Primary,表示它是首选的UserService Bean。当注入UserService类型的Bean时,Spring会优先注入userService1()方法返回的Bean。

4. 使用@Lazy延迟初始化Bean

@Lazy注解用于延迟初始化Bean。标记为@Lazy的Bean只有在第一次被请求时才会被初始化,从而减少了Spring容器的初始化时间。

以下是一个使用@Lazy注解的示例:

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;@Configuration
public class AppConfig {@Bean@Lazypublic UserService userService() {return new UserService();}
}

在上述代码中,userService()方法被标记为@Lazy,表示UserService Bean是延迟初始化的。只有在第一次请求UserService Bean时,Spring才会初始化它。

十二、Spring Bean的案例分析

为了更好地理解Spring Bean的装配方式和高级特性,以下是一个完整的案例分析。

案例背景

假设我们正在开发一个在线书店应用程序,该应用程序需要实现以下功能:

  1. 用户管理:用户可以注册、登录和浏览书籍。
  2. 书籍管理:管理员可以添加、删除和更新书籍信息。
  3. 订单管理:用户可以下单购买书籍,管理员可以处理订单。

案例实现

以下是该应用程序的实现代码:

1. 定义用户实体类

package com.example;public class User {private Long id;private String username;private String password;// Getter and Setter methodspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

2. 定义书籍实体类

package com.example;public class Book {private Long id;private String title;private String author;private double price;// Getter and Setter methodspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}

3. 定义用户服务类

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User createUser(User user) {return userRepository.save(user);}public User getUserById(Long id) {return userRepository.findById(id);}
}

4. 定义书籍服务类

package com.example;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class BookService {@Autowiredprivate BookRepository bookRepository;public Book createBook(Book book) {return bookRepository.save(book);}public Book getBookById(Long id) {return bookRepository.findById(id);}
}

5. 定义用户仓库类

package com.example;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public User save(User user) {// 模拟保存用户信息到数据库return user;}public User findById(Long id) {// 模拟从数据库中获取用户信息return new User();}
}

6. 定义书籍仓库类

package com.example;import org.springframework.stereotype.Repository;@Repository
public class BookRepository {public Book save(Book book) {// 模拟保存书籍信息到数据库return book;}public Book findById(Long id) {// 模拟从数据库中获取书籍信息return new Book();}
}

7. 定义配置类

package com.example;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();}@Beanpublic BookService bookService() {return new BookService();}
}

8. 定义主类

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在上述代码中,我们定义了用户和书籍的实体类、服务类和仓库类。通过使用@Service@Repository@Configuration注解,我们将这些类定义为Spring Bean。同时,我们使用@Autowired注解注入了依赖,使用@Bean注解定义了Bean。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/903709.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集美大学课程实验报告-实验3:栈、队列与递归

集美大学课程实验报告-实验3:栈、队列与递归项目名称 内容课程名称 数据结构班级 网安2413指导教师 郑如滨学生姓名 林沁茹学号 202421336067实验项目名称 实验3:栈、队列与递归上机实践日期上机实践时间 2学时一、目的(本次实验所涉及并要求掌握的知识点) 以下内容请根据实…

2025-03-22 闲话

2025-03-22 闲话有些闲话是纪实的,它们可能只是平淡的文字。它们可能没有感受,不带思考。你看不到装饰,只有琐碎、补也补不到自圆其说的细节。柴米油盐大抵是这样的。 来北京独居后的生活着实安逸。每天执行一个蛮正常的作息,保证三顿饮食、偶尔晚上和网友去搓搓夜宵。睡觉…

3.22 三重积分计算方法

三重积分的实际意义:计算一个立体的质量(可以) 1 投影法(先一后二)(一个土豆切成土豆丝,最后再累加Dxy平面) 一个立体图形可以看成是两个曲面拼接而成,z=(x,y)可表示一个曲面假设x和y都是确定的,然后就累加z,最后再算面积分 先假设有一条竖线,注意竖线是从哪里进入…

15.数组

数组C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。 数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。数组中的特定元素可以通过索引访问,第一个索引值为 0。声明数组在 C 中要声明一个数组,需要指定元素的类型和元素的数量 下…

逆向中简单的shellcode

做题时遇到了,简单记录一下 一,介绍: shellcode分为广义和狭义,狭义指的仅仅是通过命令行shell攻击靶机,并取得控制权的代码,广义的指能完成类似任务的代码,通常是汇编/机器码。 不过这里是RE,不是PWN,所以不会有靶机,那么在下文指的是广义的shellcode,注入程序,控…

linux一些好用命令:w,fuer,getfacl,usermod,chmod

一.命令 w w 是显示用户登录时间、空闲时间、当前执行的命令等。 2.示例 pst/* : 这是ssh登录 tty: 这是直接本地登录(ctrl+alt +F* 都可以) 这个是没本地登录显示的进程 二. 命令 fuser fuser 是一个可以查看使用此文件的进程号。 1.一般使用 fuser -a /path/to/filename…

Aligning the Objective of LLM-based Program Repair 论文笔记

介绍 (1) 发表 2025-02 ICSE24 (2) 挑战当前方法的推理目标与 LLM 的训练目标没有对齐。现有 LLM-based 方法通常采用 MLM 的方式预测修复代码(然而尽管模型参数被增大百倍但修复结果甚至没有翻一番,这与其他任务的明确可伸缩性形成对比)。因此本文假设在训练中 <masked,…

监狱智能视频分析告警系统解决方案

监狱智能视频分析告警系统解决方案能够精准监测到静坐不动、离床、攀高、独处等行为。例如,当一名囚犯长时间静坐不动时,监狱智能视频分析告警系统解决方案会自动识别并发出预警,以便管理人员及时了解情况,防止囚犯出现自伤、自残等危险行为。在洗手间场景中,系统对入厕超…

昆明理工大学最新《现代材料测试技术》复试真题及答案

-材料测试 昆工材料物理与化学、材料学、材料表征与分析、材料工程、F001现代材料测试技术、864材料科学基础、昆明理工大学材料调剂

RTT 全志D1s跑tina linux

刚毕业那会抽奖抽了一块RTT的D1S开发板,看了一下打印log就放下吃灰了。跑RT-thread的感觉折腾起来太麻烦了就让他吃灰了。最近手头有一块屏幕和一个2欧的小喇叭打算驱动一下。 正好这块板子也出来好多年了。玩一玩。首先我找到了百问网的哪吒开发板他也是D1S的,直接把他的SDK…

COMSOL 基础学习笔记

设置网格 软件通过计算网格顶点的数值,推算其他位置的数值。 行函数:移动的波。 二次行函数(除网格顶点外还计算两定点连线中心的值):网格最大长度 \(≤\frac{λ}{6}\) 一次行函数:网格最大长度 \(≤\frac{λ}{12}\) 修改方式:

NSSCTF ROUND#28 Ciallo~(∠・ω )⌒☆ WriteUp

WriteUp 题目信息 来源:NSSCTF 名称:ROUND#28 Ciallo~(∠・ω )⌒☆ 分类:Reverse 描述:无题目链接: https://www.nssctf.cn/contest/732/解题思路 首先使用DIE对文件进行查壳,发现这是一个无壳的64位exe文件。于是使用64位IDA对文件进行反汇编,得到伪代码如下:先一步步…