-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Resposta de deepseek de dia 30/09/2025
Sistema Simple de Eventos de Persistencia (Modificado)
- Clase Abstracta PersistenceEvent
java
public abstract class PersistenceEvent {
public void executePrePersist(E entity) {
// Implementación por defecto vacía
}
public void executePostPersist(E entity) {
// Implementación por defecto vacía
}
public void executePreUpdate(E entity) {
// Implementación por defecto vacía
}
public void executePostUpdate(E entity) {
// Implementación por defecto vacía
}
public void executePreRemove(E entity) {
// Implementación por defecto vacía
}
public void executePostRemove(E entity) {
// Implementación por defecto vacía
}
public void executePostLoad(E entity) {
// Implementación por defecto vacía
}
// Método abstracto para identificar si este listener aplica a una entidad específica
public abstract boolean supports(Class<?> entityClass);
}
- Manager Centralizado (Simplificado)
java
public class PersistenceEventManager {
private final Map<Class<?>, List<PersistenceEvent<?>>> entityListeners = new ConcurrentHashMap<>();
// Instancia singleton
private static PersistenceEventManager instance;
private PersistenceEventManager() {
// Constructor privado para singleton
}
// ===== SINGLETON PATTERN =====
public static synchronized PersistenceEventManager getInstance() {
if (instance == null) {
instance = new PersistenceEventManager();
}
return instance;
}
public static synchronized void destroyInstance() {
if (instance != null) {
instance.clearAllListeners();
instance = null;
System.gc(); // Sugerencia al garbage collector
}
}
public static boolean isInstanceCreated() {
return instance != null;
}
// ===== REGISTRO DE LISTENERS =====
public <E> void registerListener(Class<E> entityClass, PersistenceEvent<E> listener) {
entityListeners
.computeIfAbsent(entityClass, k -> new CopyOnWriteArrayList<>())
.add(listener);
}
public <E> void unregisterListener(Class<E> entityClass, PersistenceEvent<E> listener) {
List<PersistenceEvent<?>> listeners = entityListeners.get(entityClass);
if (listeners != null) {
listeners.remove(listener);
// Si no quedan listeners para esta entidad, eliminar la entrada
if (listeners.isEmpty()) {
entityListeners.remove(entityClass);
}
}
}
public void unregisterAllListenersForEntity(Class<?> entityClass) {
entityListeners.remove(entityClass);
}
public void clearAllListeners() {
entityListeners.clear();
}
// ===== MÉTODOS DE DISPARO =====
@SuppressWarnings("unchecked")
public <E> void firePrePersist(E entity) {
if (entity == null) return;
fireEvent(entity, "executePrePersist");
}
@SuppressWarnings("unchecked")
public <E> void firePostPersist(E entity) {
if (entity == null) return;
fireEvent(entity, "executePostPersist");
}
@SuppressWarnings("unchecked")
public <E> void firePreUpdate(E entity) {
if (entity == null) return;
fireEvent(entity, "executePreUpdate");
}
@SuppressWarnings("unchecked")
public <E> void firePostUpdate(E entity) {
if (entity == null) return;
fireEvent(entity, "executePostUpdate");
}
@SuppressWarnings("unchecked")
public <E> void firePreRemove(E entity) {
if (entity == null) return;
fireEvent(entity, "executePreRemove");
}
@SuppressWarnings("unchecked")
public <E> void firePostRemove(E entity) {
if (entity == null) return;
fireEvent(entity, "executePostRemove");
}
@SuppressWarnings("unchecked")
public <E> void firePostLoad(E entity) {
if (entity == null) return;
fireEvent(entity, "executePostLoad");
}
// ===== MÉTODO PRIVADO PARA DISPARAR EVENTOS =====
@SuppressWarnings("unchecked")
private <E> void fireEvent(E entity, String methodName) {
Class<?> entityClass = entity.getClass();
// Buscar listeners específicos para esta entidad
List<PersistenceEvent<?>> specificListeners = entityListeners.get(entityClass);
if (specificListeners != null) {
for (PersistenceEvent<?> listener : specificListeners) {
if (listener.supports(entityClass)) {
invokeMethod(listener, entity, methodName);
}
}
}
// Buscar listeners para Object.class (aplican a todas las entidades)
List<PersistenceEvent<?>> globalListeners = entityListeners.get(Object.class);
if (globalListeners != null) {
for (PersistenceEvent<?> listener : globalListeners) {
if (listener.supports(entityClass)) {
invokeMethod(listener, entity, methodName);
}
}
}
}
@SuppressWarnings("unchecked")
private <E> void invokeMethod(PersistenceEvent<?> listener, E entity, String methodName) {
try {
Method method = listener.getClass().getMethod(methodName, Object.class);
method.invoke(listener, entity);
} catch (Exception e) {
System.err.println("Error invoking method " + methodName + " on listener: " + e.getMessage());
}
}
// ===== UTILIDADES =====
public <E> boolean hasListeners(Class<E> entityClass) {
List<PersistenceEvent<?>> listeners = entityListeners.get(entityClass);
return listeners != null && !listeners.isEmpty();
}
public <E> int getListenerCount(Class<E> entityClass) {
List<PersistenceEvent<?>> listeners = entityListeners.get(entityClass);
return listeners != null ? listeners.size() : 0;
}
public int getTotalListenerCount() {
return entityListeners.values().stream()
.mapToInt(List::size)
.sum();
}
public Set<Class<?>> getRegisteredEntityClasses() {
return new HashSet<>(entityListeners.keySet());
}
}
- Configuración Estática
java
public class PersistenceEventConfig {
// ===== REGISTRO DE EVENTOS =====
public static <E> void registerEvent(Class<E> entityClass, PersistenceEvent<E> listener) {
PersistenceEventManager manager = PersistenceEventManager.getInstance();
manager.registerListener(entityClass, listener);
System.out.println("Listener registrado para entidad: " + entityClass.getSimpleName());
}
public static <E> void unregisterEvent(Class<E> entityClass, PersistenceEvent<E> listener) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager manager = PersistenceEventManager.getInstance();
manager.unregisterListener(entityClass, listener);
System.out.println("Listener desregistrado para entidad: " + entityClass.getSimpleName());
// Verificar si el manager puede ser destruido
checkAndDestroyManager();
}
}
public static void unregisterAllEventsForEntity(Class<?> entityClass) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager manager = PersistenceEventManager.getInstance();
manager.unregisterAllListenersForEntity(entityClass);
System.out.println("Todos los listeners desregistrados para: " + entityClass.getSimpleName());
// Verificar si el manager puede ser destruido
checkAndDestroyManager();
}
}
public static void unregisterAllEvents() {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager manager = PersistenceEventManager.getInstance();
manager.clearAllListeners();
System.out.println("Todos los listeners desregistrados");
// Forzar destrucción del manager
PersistenceEventManager.destroyInstance();
}
}
// ===== VERIFICACIÓN Y LIMPIEZA =====
private static void checkAndDestroyManager() {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager manager = PersistenceEventManager.getInstance();
// Si no hay listeners registrados, destruir el manager
if (manager.getTotalListenerCount() == 0) {
System.out.println("No hay listeners registrados. Destruyendo PersistenceEventManager...");
PersistenceEventManager.destroyInstance();
}
}
}
// ===== INFORMACIÓN DEL ESTADO =====
public static boolean isManagerActive() {
return PersistenceEventManager.isInstanceCreated();
}
public static int getTotalRegisteredListeners() {
if (PersistenceEventManager.isInstanceCreated()) {
return PersistenceEventManager.getInstance().getTotalListenerCount();
}
return 0;
}
public static Set<Class<?>> getRegisteredEntities() {
if (PersistenceEventManager.isInstanceCreated()) {
return PersistenceEventManager.getInstance().getRegisteredEntityClasses();
}
return Collections.emptySet();
}
}
- EntityListener de JPA (Actualizado)
java
@component
public class GlobalJpaEventListener {
@PrePersist
public void prePersist(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePrePersist(entity);
}
}
@PostPersist
public void postPersist(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePostPersist(entity);
}
}
@PreUpdate
public void preUpdate(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePreUpdate(entity);
}
}
@PostUpdate
public void postUpdate(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePostUpdate(entity);
}
}
@PreRemove
public void preRemove(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePreRemove(entity);
}
}
@PostRemove
public void postRemove(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePostRemove(entity);
}
}
@PostLoad
public void postLoad(Object entity) {
if (PersistenceEventManager.isInstanceCreated()) {
PersistenceEventManager.getInstance().firePostLoad(entity);
}
}
}
- Ejemplos de Implementaciones Concretas
java
// Listener de Auditoría
public class AuditPersistenceEvent extends PersistenceEvent {
@Override
public void executePrePersist(Object entity) {
if (entity instanceof Auditable) {
Auditable auditable = (Auditable) entity;
auditable.setCreatedAt(LocalDateTime.now());
auditable.setCreatedBy(getCurrentUser());
}
}
@Override
public void executePreUpdate(Object entity) {
if (entity instanceof Auditable) {
Auditable auditable = (Auditable) entity;
auditable.setUpdatedAt(LocalDateTime.now());
auditable.setUpdatedBy(getCurrentUser());
}
}
@Override
public boolean supports(Class<?> entityClass) {
return Auditable.class.isAssignableFrom(entityClass);
}
private String getCurrentUser() {
return "system";
}
}
// Listener Específico para Usuario
public class UsuarioPersistenceEvent extends PersistenceEvent {
@Override
public void executePrePersist(Usuario usuario) {
if (usuario.getEmail() != null && !usuario.getEmail().contains("@")) {
throw new IllegalArgumentException("Email inválido para usuario: " + usuario.getEmail());
}
usuario.setActivo(true);
}
@Override
public void executePostLoad(Usuario usuario) {
if (usuario.getNombre() != null && usuario.getApellido() != null) {
usuario.setNombreCompleto(usuario.getNombre() + " " + usuario.getApellido());
}
}
@Override
public boolean supports(Class<?> entityClass) {
return Usuario.class.equals(entityClass);
}
}
- Uso del Sistema
java
@service
public class UsuarioService {
@Autowired
private UsuarioRepository usuarioRepository;
@PostConstruct
public void init() {
// Registrar eventos estáticamente
PersistenceEventConfig.registerEvent(Usuario.class, new UsuarioPersistenceEvent());
PersistenceEventConfig.registerEvent(Object.class, new AuditPersistenceEvent());
}
@PreDestroy
public void cleanup() {
// Limpiar todos los eventos al destruir el servicio
PersistenceEventConfig.unregisterAllEventsForEntity(Usuario.class);
}
@Transactional
public Usuario crearUsuario(Usuario usuario) {
return usuarioRepository.save(usuario);
}
}
// Uso en cualquier parte de la aplicación
@component
public class OtroComponente {
public void configurarEventos() {
// Registrar nuevo listener dinámicamente
PersistenceEventConfig.registerEvent(Producto.class, new ProductoPersistenceEvent());
// Verificar estado
System.out.println("Manager activo: " + PersistenceEventConfig.isManagerActive());
System.out.println("Listeners registrados: " + PersistenceEventConfig.getTotalRegisteredListeners());
}
public void limpiarEventos() {
// Desregistrar eventos específicos
PersistenceEventConfig.unregisterAllEventsForEntity(Producto.class);
// O limpiar todo
PersistenceEventConfig.unregisterAllEvents();
}
}
- Controlador para Gestión
java
@RestController
@RequestMapping("/api/persistence-events")
public class PersistenceEventController {
@PostMapping("/register/{entityName}")
public String registerEvent(@PathVariable String entityName) {
try {
Class<?> entityClass = Class.forName("com.tudominio.entities." + entityName);
// Aquí podrías tener lógica para crear el listener apropiado
if (entityName.equals("Usuario")) {
PersistenceEventConfig.registerEvent(entityClass, new UsuarioPersistenceEvent());
} else if (entityName.equals("Producto")) {
PersistenceEventConfig.registerEvent(entityClass, new ProductoPersistenceEvent());
}
return "Evento registrado para: " + entityName;
} catch (ClassNotFoundException e) {
return "Entidad no encontrada: " + entityName;
}
}
@PostMapping("/unregister/{entityName}")
public String unregisterEvent(@PathVariable String entityName) {
try {
Class<?> entityClass = Class.forName("com.tudominio.entities." + entityName);
PersistenceEventConfig.unregisterAllEventsForEntity(entityClass);
return "Eventos desregistrados para: " + entityName;
} catch (ClassNotFoundException e) {
return "Entidad no encontrada: " + entityName;
}
}
@GetMapping("/status")
public Map<String, Object> getStatus() {
return Map.of(
"managerActive", PersistenceEventConfig.isManagerActive(),
"totalListeners", PersistenceEventConfig.getTotalRegisteredListeners(),
"registeredEntities", PersistenceEventConfig.getRegisteredEntities()
.stream()
.map(Class::getSimpleName)
.collect(Collectors.toList()),
"timestamp", LocalDateTime.now()
);
}
}
🚀 Características Principales del Nuevo Diseño
✅ Clase abstracta en lugar de interface
✅ Singleton pattern para el manager
✅ Gestión automática de memoria (se destruye cuando no hay listeners)
✅ API estática simple para registro/desregistro
✅ Zero config - no necesita @Autowired ni @Component
✅ Lazy initialization - solo se crea cuando se necesita
¿Te gusta este enfoque más simplificado?
Metadata
Metadata
Assignees
Type
Projects
Status