Quiz: Beans y Contexto Spring
Ponga a prueba sus conocimientos sobre beans y el contexto de aplicación.
30 preguntas - Haga clic en cada pregunta para revelar la respuesta.
Preguntas 1-15: Beans
Pregunta 1: ¿Qué es un bean Spring?
Respuesta: Un bean es un objeto gestionado por el contenedor IoC de Spring:
- Creado y configurado por Spring
- Inyección de dependencias automática
- Ciclo de vida gestionado
- Singleton por defecto
Pregunta 2: ¿Cómo declarar un bean con una anotación?
Respuesta:
// Con estereotipo (escaneo automático)
@Component
public class MyService { }
@Service
public class UserService { }
@Repository
public class UserRepository { }
@Controller
public class UserController { }
Pregunta 3: ¿Cómo declarar un bean con @Bean?
Respuesta:
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.registerModule(new JavaTimeModule());
}
}
Pregunta 4: ¿Cuál es la diferencia entre @Component y @Bean?
Respuesta:
| @Component | @Bean |
|---|---|
| Sobre una clase | Sobre un método |
| Detectado automáticamente por escaneo | Declarado explícitamente |
| Clases que usted controla | Clases de terceros |
| Configuración limitada | Control total |
Pregunta 5: ¿Cuál es el nombre por defecto de un bean?
Respuesta: El nombre de la clase en camelCase:
@Component
public class UserService { }
// Nombre: userService
@Bean
public RestTemplate myRestTemplate() { }
// Nombre: myRestTemplate
Personalizar:
@Component("customName")
@Bean("customName")
Pregunta 6: ¿Cómo recuperar un bean por su nombre?
Respuesta:
@Autowired
private ApplicationContext context;
public void example() {
UserService service = context.getBean("userService", UserService.class);
// O por tipo
UserService service = context.getBean(UserService.class);
}
Pregunta 7: ¿Qué es el ciclo de vida de un bean?
Respuesta:
- Instanciación: creación del objeto
- Inyección: inyección de dependencias
- Inicialización: métodos @PostConstruct
- Uso: bean listo
- Destrucción: métodos @PreDestroy
Pregunta 8: ¿Cómo ejecutar código después de la inicialización?
Respuesta:
@Component
public class DataLoader {
@PostConstruct
public void init() {
log.info("Bean inicializado");
loadData();
}
}
// O con @Bean
@Bean(initMethod = "init")
public MyService myService() { }
Pregunta 9: ¿Cómo ejecutar código antes de la destrucción?
Respuesta:
@Component
public class ResourceManager {
@PreDestroy
public void cleanup() {
log.info("Limpieza de recursos");
closeConnections();
}
}
// O con @Bean
@Bean(destroyMethod = "close")
public DataSource dataSource() { }
Pregunta 10: ¿Qué son InitializingBean y DisposableBean?
Respuesta: Interfaces alternativas para el ciclo de vida:
@Component
public class MyBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
// Después de la inyección
}
@Override
public void destroy() {
// Antes de la destrucción
}
}
Se recomienda @PostConstruct/@PreDestroy para menor acoplamiento.
Pregunta 11: ¿Cómo implementar ApplicationRunner?
Respuesta:
@Component
public class StartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
log.info("Aplicación iniciada");
// Argumentos: args.getOptionValues("config")
}
}
Se ejecuta después del arranque completo del contexto.
Pregunta 12: ¿Cómo implementar CommandLineRunner?
Respuesta:
@Component
public class DataInitializer implements CommandLineRunner {
private final UserRepository repository;
@Override
public void run(String... args) {
repository.save(new User("Admin"));
log.info("Datos inicializados");
}
}
Pregunta 13: ¿Cómo ordenar la ejecución de los runners?
Respuesta:
@Component
@Order(1)
public class FirstRunner implements CommandLineRunner { }
@Component
@Order(2)
public class SecondRunner implements CommandLineRunner { }
Pregunta 14: ¿Cómo crear un bean condicional?
Respuesta:
@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() { }
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() { }
@Bean
@Profile("dev")
public DevService devService() { }
Pregunta 15: ¿Qué es @Lazy?
Respuesta: Retrasa la creación del bean hasta el primer acceso:
@Component
@Lazy
public class HeavyService {
public HeavyService() {
// Llamado solo en el primer acceso
}
}
// O en la inyección
public MyController(@Lazy HeavyService service) { }
Preguntas 16-30: Contexto y Ámbitos
Pregunta 16: ¿Qué es el ApplicationContext?
Respuesta: El contenedor central de Spring que:
- Gestiona todos los beans
- Proporciona inyección de dependencias
- Publica eventos
- Carga recursos
- Gestiona la internacionalización
Pregunta 17: ¿Cuáles son los ámbitos de beans disponibles?
Respuesta:
| Ámbito | Descripción |
|---|---|
singleton | Una instancia por contexto (por defecto) |
prototype | Nueva instancia en cada solicitud |
request | Una instancia por solicitud HTTP |
session | Una instancia por sesión HTTP |
application | Una instancia por ServletContext |
Pregunta 18: ¿Cómo definir el ámbito de un bean?
Respuesta:
@Component
@Scope("prototype")
public class PrototypeBean { }
@Bean
@Scope("request")
public RequestContext requestContext() { }
// O con constantes
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Pregunta 19: ¿Qué problema surge al inyectar un prototype en un singleton?
Respuesta: El singleton siempre mantiene la misma instancia del prototype:
@Component // Singleton
public class SingletonService {
private final PrototypeBean proto; // ¡Siempre la misma instancia!
public SingletonService(PrototypeBean proto) {
this.proto = proto;
}
}
Solución: usar ObjectProvider o @Lookup.
Pregunta 20: ¿Cómo usar ObjectProvider?
Respuesta:
@Component
public class SingletonService {
private final ObjectProvider<PrototypeBean> protoProvider;
public void doWork() {
PrototypeBean proto = protoProvider.getObject(); // Nueva instancia
}
}
Pregunta 21: ¿Cómo usar @Lookup?
Respuesta:
@Component
public abstract class SingletonService {
@Lookup
protected abstract PrototypeBean getPrototype();
public void doWork() {
PrototypeBean proto = getPrototype(); // Nueva instancia
}
}
Pregunta 22: ¿Cómo escuchar eventos del contexto?
Respuesta:
@Component
public class ContextListener {
@EventListener
public void onContextRefreshed(ContextRefreshedEvent event) {
log.info("Contexto refrescado");
}
@EventListener
public void onContextClosed(ContextClosedEvent event) {
log.info("Contexto cerrado");
}
}
Pregunta 23: ¿Cómo publicar un evento personalizado?
Respuesta:
// Evento
public class UserCreatedEvent extends ApplicationEvent {
private final User user;
public UserCreatedEvent(Object source, User user) {
super(source);
this.user = user;
}
}
// Publicación
@Service
public class UserService {
private final ApplicationEventPublisher publisher;
public void createUser(User user) {
userRepository.save(user);
publisher.publishEvent(new UserCreatedEvent(this, user));
}
}
// Escucha
@Component
public class UserEventListener {
@EventListener
public void onUserCreated(UserCreatedEvent event) {
log.info("Usuario creado: {}", event.getUser().getName());
}
}
Pregunta 24: ¿Cómo escuchar un evento de forma asíncrona?
Respuesta:
@EnableAsync
@Configuration
public class AsyncConfig { }
@Component
public class AsyncListener {
@Async
@EventListener
public void onEvent(MyEvent event) {
// Ejecutado en otro hilo
}
}
Pregunta 25: ¿Cómo acceder al entorno de Spring?
Respuesta:
@Component
public class ConfigService {
private final Environment env;
public ConfigService(Environment env) {
this.env = env;
}
public void showConfig() {
String property = env.getProperty("app.name");
String[] profiles = env.getActiveProfiles();
boolean isDev = env.acceptsProfiles(Profiles.of("dev"));
}
}
Pregunta 26: ¿Cómo cargar recursos externos?
Respuesta:
@Component
public class ResourceLoader {
@Value("classpath:data/config.json")
private Resource configResource;
public void load() throws IOException {
String content = new String(configResource.getInputStream().readAllBytes());
}
}
Pregunta 27: ¿Cómo implementar EnvironmentPostProcessor?
Respuesta:
public class CustomEnvProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
// Modificar el entorno antes del arranque
Map<String, Object> props = new HashMap<>();
props.put("custom.property", "value");
env.getPropertySources().addFirst(new MapPropertySource("custom", props));
}
}
Registrar en META-INF/spring.factories.
Pregunta 28: ¿Cómo usar los perfiles de Spring?
Respuesta:
// Bean activo solo en dev
@Component
@Profile("dev")
public class DevOnlyService { }
// Bean activo excepto en prod
@Component
@Profile("!prod")
public class NonProdService { }
// Varios perfiles
@Component
@Profile({"dev", "test"})
public class DevTestService { }
Pregunta 29: ¿Cómo definir beans en configuraciones separadas?
Respuesta:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() { }
}
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain() { }
}
@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig { }
Pregunta 30: ¿Cómo probar un contexto Spring?
Respuesta:
@SpringBootTest
class ContextTest {
@Autowired
private ApplicationContext context;
@Test
void contextLoads() {
assertThat(context).isNotNull();
assertThat(context.getBean(UserService.class)).isNotNull();
}
@Test
void beanExists() {
assertThat(context.containsBean("userService")).isTrue();
}
}
Puntuación
| Puntuación | Nivel |
|---|---|
| 27-30 | Excelente - Beans y contexto dominados |
| 21-26 | Bien - Algunas revisiones |
| 15-20 | Medio - Repase el capítulo |
| Menos de 15 | A revisar |