Saltar al contenido principal

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 claseSobre un método
Detectado automáticamente por escaneoDeclarado explícitamente
Clases que usted controlaClases de terceros
Configuración limitadaControl 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:

  1. Instanciación: creación del objeto
  2. Inyección: inyección de dependencias
  3. Inicialización: métodos @PostConstruct
  4. Uso: bean listo
  5. 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:

ÁmbitoDescripción
singletonUna instancia por contexto (por defecto)
prototypeNueva instancia en cada solicitud
requestUna instancia por solicitud HTTP
sessionUna instancia por sesión HTTP
applicationUna 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ónNivel
27-30Excelente - Beans y contexto dominados
21-26Bien - Algunas revisiones
15-20Medio - Repase el capítulo
Menos de 15A revisar

Volver al Módulo 5