These annotations are based on the MVC pattern. Namely:
Classes decorated with the @Controller
annotation serve as the MVC C. It should be noted that the real controller in Spring MVC is the class DispatchServlet
that will use the specific @Controller
classes to attend the requests based on the mapping of the declared URLs.
Classes decorated with the @Service
notation should serve for your service layer or business logic. This is where you put the business logic of your application, business rules, among others .
Classes decorated with the annotation @Repository
should serve for the data access layer. Here you should place the CRUD logic: insert, update (update), deletion (physical and / or logical), queries (select).
The @Service
, @Repository
and your entity classes will be the MVC M. Your JSP files and other view technologies (JSTL, mustache, etc) make up the MVC V.
The @Controller
classes should only access the @Service
classes through interfaces. Similarly, the @Service
classes should only access other classes @Service
and a specific set of classes @Repository
through interfaces.
Example:
//Entidades
public class Recibo {
private List<DetalleRecibo>
}
public class Producto { }
public class DetalleRecibo {
Producto producto;
}
//DAOs, Repositorios, etc
public interface ReciboDao {
void guardar(Recibo recibo);
}
//nota: estas anotaciones van a nivel de clase, NO a nivel de interfaz
@Repository
public class ReciboDaoImpl implements ReciboDao {
//implementa los métodos
//puede mandarlo a archivo, usar JDBC u otro framework
//como Hibernate, JPA, MyBatis, jOOQ
//o usar un repositorio de datos externo como servicios REST
}
public interface ProductoDao {
Producto obtener(int id);
void actualizar(Producto producto);
}
@Repository
public class ProductoDaoImpl implements ProductoDao {
//implementación...
}
//Service
public interface ProductoService {
Producto obtener(int id);
void actualizarStock(Producto productoConStockActualizado);
}
@Service
public class ProductoServiceImpl implements ProductoService {
//se le asocia al ProductoDao (interfaz)
//ojo que debería acceder de manera vertical/jerárquica
//al dao asociado a la entidad Producto
@Autowired
private ProductoDao productoDao;
@Override
public Producto obtener(int id) {
return productoDao.obtener(id);
}
@Override
public void actualizarStock(Producto productoConStockActualizado) {
//ejemplo minimalista y básico
//la implementación de un caso de uso como el de aquí debería
//considerar más elementos
Producto actual = obtener(productoConStockActualizado.getId());
if (actual.getStock() - productoConStockActualizado.getStock() < 0)
throw new MiExcepcion("Producto no puede tener stock negativo");
productoDao.actualizar(productoConStockActualizado);
}
}
public interface ReciboService {
Recibo generaRecibo(List<DetalleRecibo> listaDetalleRecibo);
void guardar(Recibo recibo);
}
@Service
public class ReciboServiceImpl {
//se le asocia a ReciboDao, similar a la relación
//entre ProductoService y ProductoDao
@Autowired
private ReciboDao reciboDao;
//Nota: si ReciboServiceImpl quiere consultar u operar
//con la información de la entidad Producto
//en lugar de asociarse a ProductoDao se asociará
//a ProductoService puesto que su implementación posee
//reglas de negocio a usar en la aplicación
@Autowired
private ProductoService productoService;
@Override
public Recibo generaRecibo(List<DetalleRecibo> listaDetalleRecibo) {
//usar la información de detalle del recibo
//para armar y generar un recibo
//ejemplo
for (DetalleRecibo detalle : listaDetalleRecibo) {
Producto producto = detalle.getProducto();
productoService.actualizarStock(producto);
}
//más procesamiento...
//se retorna el recibo generado
}
@Override
public void guardar(Recibo recibo) {
reciboDao.guardar(recibo);
}
}
@Controller
public class VentaController {
@Autowired
private ReciboService reciboService;
@RequestMapping(...)
public void guardaRecibo() {
//procesa la información recibida
//genera el recibo, lo guarda, etc...
}
}
Adapted from my response on the English site .