Backend Development 8 min read

Using Custom Annotations, Abstract Classes, and Interfaces in Spring Backend Development

This article demonstrates how to create and apply custom Spring annotations for AOP logging, implements the corresponding aspect, and discusses the strategic use of abstract classes and interfaces to separate business logic from data access in both MongoDB and MySQL contexts.

Java Captain
Java Captain
Java Captain
Using Custom Annotations, Abstract Classes, and Interfaces in Spring Backend Development

6. Custom Annotations

Spring custom annotations allow flexible AOP operations during project development, especially when placed on interface methods. The example shows a global request‑operation log persistence using a custom annotation.

6.1 Define Annotation

The annotation definition includes retention, target, and inherited settings, along with attributes for a track ID and an operation enum.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface OperateLog {
    /**
     * Track ID
     */
    String trackId() default "";
    /**
     * Specific operation behavior
     */
    OperationEnum operation();
}

The OperationEnum must be prepared beforehand to describe concrete actions.

@Getter
@RequiredArgsConstructor
public enum OperationEnum {
    XX_MODULE_ADD("xx模块", "新增xx"),
    XX_MODULE_UPDATE("xx模块", "修改xx");
    private final String module;
    private final String detail;
}

6.2 Aspect Implementation

The aspect determines when the annotated method is intercepted; for logging, @AfterReturning is typical, while authentication may use @Before . The following aspect extracts annotation parameters, builds a log entity, and persists it.

@Aspect
@Component
public class OperateLogAOP {
    @Resource
    private OperationLogService operationLogService;

    /**
     * Executes after the method returns, recording the operation log.
     */
    @AfterReturning(value = "@annotation(operateLog)")
    public void operateLogAopMethod(JoinPoint joinPoint, OperateLog operateLog) {
        String trackId = operateLog.trackId();
        Assert.hasText(trackId, "trackId param error!");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        String businessLogId = (String) AopUtils.getFieldValue(args, methodSignature, trackId);
        String module = operateLog.operation().getModule();
        String detail = operateLog.operation().getDetail();
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        OperationLog operationLog = OperationLog.builder()
                .trackId(businessLogId)
                .module(module)
                .detail(detail)
                .ip(IpUtil.getUserIp(request))
                .createTime(new Date())
                .operatorUuid(UserDataBuilder.get().getUserUuid())
                .operatorName(UserDataBuilder.get().getUserName())
                .build();
        operationLogService.save(operationLog);
    }
}

6.3 Business Usage

After defining the annotation and aspect, place the annotation on controller methods to automatically record logs.

@PostMapping("update")
@OperateLog(trackId = "studyDTO.id", operation = OperationEnum.XX_MODULE_UPDATE)
public BaseResponse
updateStudy(@RequestBody StudyDTO studyDTO) {
    return ResultUtils.success(studyService.updateStudy(studyDTO));
}

7. Abstract Classes and Interfaces

Using abstract classes and interfaces correctly reduces coupling and improves code reuse. Abstract classes share common features, while interfaces decouple contracts from implementations.

7.1 Isolate Business Layer from ORM Layer

MongoDB Example

@Service
public class WorkerServiceImpl extends AbstractWorkerServiceImpl implements WorkerService {}

public abstract class AbstractWorkerServiceImpl extends BaseServiceImpl
implements IWorkerService {}

public interface WorkerService extends IWorkerService {}

public interface IWorkerService extends BaseService
{}

public abstract class BaseServiceImpl
implements BaseService
{}

MySQL Example

@Service
public class StudyServiceImpl extends ServiceImpl
implements StudyService {}

public interface StudyService extends IService
{}

public class ServiceImpl
, T> implements IService
{}

7.2 Isolate Subsystem Business Implementation

The Facade pattern provides a simple entry point for subsystems, hiding complexity.

/** Only cares about data, essentially database operations */
@Service
public class PersonService extends ServiceImpl
{
    @Resource
    private PersonMapper mapper;
    // other DB statements
}

/** Only cares about business, referenced by controller */
@Service
public class PersonFacade {
    @Resource
    private PersonService service;
    // business logic methods
}

This separation clarifies responsibilities between data handling and business processing.

7.3 Choice Comparison

In practice, choose either abstract classes or interfaces for isolating business from data; the combination best reflects Java's inheritance, encapsulation, and polymorphism principles.

Article Summary

This second article in the development‑tips series introduces practical techniques for custom Spring annotations, AOP logging, and the disciplined use of abstract classes and interfaces to structure backend services, with concrete code examples for both MongoDB and MySQL.

JavaAOPSpringCustom AnnotationinterfaceAbstract Class
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.