انتقل إلى المحتوى الرئيسي

الوحدة 18: أسئلة المقابلة Spring Boot

الأهداف​

تُعدك هذه الوحدة لـ المقابلات التقنية في تطوير Java/Spring Boot. الأسئلة منظمة حسب مستوى الصعوبة والموضوع، وتغطي المواضيع الأكثر شيوعًا في المقابلات.

نصيحة

لا تقم بحفظ الإجابات كلمة بكلمة. افهم المفاهيم وكن قادرًا على شرحها بكلماتك الخاصة مع أمثلة ملموسة.


فصول الوحدة​

#الفصلالمحتوى
1JPA وقاعدة البياناتمشكلة N+1، التحميل الكسول/النشط، @Transactional، الترقيم، العلاقات بين الكيانات
2تمارين إعادة الهيكلةعبارات الحراسة، نمط الاستراتيجية، SRP (God Class)، الثوابت السحرية، التركيب مقابل الوراثة
3الخوارزميات وهياكل البياناتHashMap، Stack، LinkedList، البحث الثنائي، Two Sum، FizzBuzz، التباديل
4تصميم REST وأنماط التصميمAPI REST، Builder، Singleton، Observer مع أحداث Spring
5تصحيح الأخطاء ومراجعة الكودالعثور على الأخطاء، مراجعة الكود، تسرب الذاكرة، التزامن، الاستثناءات، روائح الكود
6فخاخ Java الأساسية== مقابل .equals()، hashCode()، final، static، String غير قابل للتغيير، Optional، المرور بالقيمة
7مجموعات JavaList.of() مقابل new ArrayList<>()، HashMap، HashSet، Stream API، أمان الخيوط، التكرار
8"ما هو...؟" — 30 مفهومًاDTO، MVC، API REST، CRUD، POJO، Bean، IoC، ORM/JPA، Maven، Docker، JWT، CORS، Lombok، Record...

المستوى 1: أسئلة أساسية​

س1. ما هو Spring Boot وكيف يختلف عن Spring Framework؟​

الإجابة المتوقعة:

Spring Boot هو إطار عمل مبني فوق Spring Framework الذي يبسط التكوين والنشر. الفروقات الرئيسية:

الجانبSpring FrameworkSpring Boot
التكوينيدوي (XML أو Java)التكوين التلقائي
الخادمخادم خارجي مطلوبخادم مدمج (Tomcat)
التبعياتتُدار بشكل فرديStarters مُعدة مسبقًا
البدءمعقدmain() + @SpringBootApplication

Spring Boot لا يستبدل Spring، بل يجعله أسهل في الاستخدام.


س2. ماذا تفعل التعليمة @SpringBootApplication؟​

الإجابة المتوقعة:

هي تعليمة ميتا تجمع بين ثلاث تعليمات:

  • @SpringBootConfiguration : تشير إلى فئة تكوين Spring
  • @EnableAutoConfiguration : تُفعل التكوين التلقائي بناءً على تبعيات classpath
  • @ComponentScan : تفحص الحزمة الحالية وحزمها الفرعية للعثور على beans

س3. ما هو حقن التبعيات (DI)؟​

الإجابة المتوقعة:

حقن التبعيات هو نمط تصميم حيث تُوفر تبعيات كائن من الخارج بدلاً من إنشائها بواسطة الكائن نفسه.

// بدون DI (ترابط قوي)
public class OrderService {
private UserRepository repo = new UserRepository(); // ينشئ تبعيته الخاصة
}

// مع DI (ترابط ضعيف)
public class OrderService {
private final UserRepository repo;

public OrderService(UserRepository repo) { // تُحقن من الخارج
this.repo = repo;
}
}

الفوائد: القابلية للاختبار، فك الترابط، المرونة.


س4. ما الفرق بين @Controller و @RestController؟​

الإجابة المتوقعة:

  • @Controller يعيد أسماء العرض (قوالب HTML). لإعادة JSON، يجب إضافة @ResponseBody على كل طريقة.
  • @RestController = @Controller + @ResponseBody. كل طريقة تعيد مباشرة بيانات مسلسلة في JSON.

س5. ما هي النطاقات المختلفة للـ bean في Spring؟​

الإجابة المتوقعة:

النطاقالوصف
singletonمثيل واحد لكل حاوية (افتراضي)
prototypeمثيل جديد عند كل حقن
requestمثيل واحد لكل طلب HTTP
sessionمثيل واحد لكل جلسة HTTP
applicationمثيل واحد لكل ServletContext

س6. ما الفرق بين application.properties و application.yml؟​

الإجابة المتوقعة:

نفس الوظيفة، صيغة مختلفة:

# application.properties (مفتاح=قيمة، مسطح)
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
# application.yml (هرمي، أكثر قابلية للقراءة)
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb

YAML أكثر قابلية للقراءة للتكوينات المتداخلة، لكن احذر من المسافات البادئة.


س7. ما هو Starter Spring Boot؟​

الإجابة المتوقعة:

الـ starter هو مجموعة من التبعيات المُعدة مسبقًا لاستخدام معين:

  • spring-boot-starter-web : تطبيق ويب (Tomcat، Spring MVC، Jackson)
  • spring-boot-starter-data-jpa : الاستمرارية (Hibernate، Spring Data JPA)
  • spring-boot-starter-security : الأمان (Spring Security)
  • spring-boot-starter-test : الاختبارات (JUnit، Mockito، MockMvc)

تجنب إدارة التوافقات بين الإصدارات يدويًا.


المستوى 2: أسئلة متوسطة​

س8. اشرح بنية الطبقات لتطبيق Spring Boot.​

الإجابة المتوقعة:

عميل HTTP
↓
┌─────────────────┐
│ Controller │ يستقبل الطلبات، يتحقق منها، يعيد الردود
├─────────────────┤
│ Service │ المنطق التجاري، القواعد التجارية، التنسيق
├─────────────────┤
│ Repository │ الوصول إلى البيانات (CRUD، استعلامات قاعدة البيانات)
├─────────────────┤
│ Database │ PostgreSQL، MySQL، H2...
└─────────────────┘

كل طبقة تتواصل فقط مع الطبقة التي تحتها مباشرة. الـ Controller لا يصل أبدًا مباشرة إلى الـ Repository.


س9. ما الفرق بين JpaRepository، CrudRepository و PagingAndSortingRepository؟​

الإجابة المتوقعة:

JpaRepository (الأكثر شمولاً)
↑ يرث من
PagingAndSortingRepository (الترقيم + الفرز)
↑ يرث من
CrudRepository (CRUD الأساسي)
↑ يرث من
Repository (علامة)
  • CrudRepository : save(), findById(), findAll(), deleteById()
  • PagingAndSortingRepository : يضيف findAll(Pageable), findAll(Sort)
  • JpaRepository : يضيف flush(), saveAndFlush(), deleteInBatch(), يعيد List بدلاً من Iterable

في الممارسة، نستخدم دائمًا تقريبًا JpaRepository.


س10. كيف تعمل التكوين التلقائي في Spring Boot؟​

الإجابة المتوقعة:

يفحص Spring Boot classpath عند البدء ويكوّن تلقائيًا الـ beans اللازمة:

  1. إذا كان spring-boot-starter-data-jpa في classpath وتم تكوين DataSource → يكوّن تلقائيًا Hibernate، EntityManager، إلخ.
  2. إذا كان spring-boot-starter-web في classpath → يكوّن تلقائيًا Tomcat، Jackson، DispatcherServlet
  3. تحدد التعليمة @ConditionalOn... ما إذا كان التكوين التلقائي ينطبق

يمكننا دائمًا تجاوز الـ beans المكونة تلقائيًا باستخدام @Bean الخاصة بنا.


س11. ما هي Spring Profiles وما فائدتها؟​

الإجابة المتوقعة:

تسمح الـ profiles بتحميل تكوينات مختلفة حسب البيئة:

# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:devdb

# application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-server:5432/mydb

التفعيل: --spring.profiles.active=prod أو SPRING_PROFILES_ACTIVE=prod

يمكننا أيضًا تقييد الـ beans باستخدام @Profile("dev").


س12. اشرح الفرق بين @Transactional في القراءة والكتابة.​

الإجابة المتوقعة:

@Transactional(readOnly = true)   // قراءة: تحسين Hibernate (لا يوجد فحص قذر)
public List<User> findAll() { ... }

@Transactional // كتابة: commit إذا نجح، rollback إذا حدث استثناء
public User create(UserDto dto) { ... }

أفضل ممارسة: وضع @Transactional(readOnly = true) على مستوى فئة الخدمة، و@Transactional على طرق الكتابة فقط.


س13. كيف ندير الاستثناءات في API REST Spring Boot؟​

الإجابة المتوقعة:

ثلاثة نهج، من الأكثر محلية إلى الأكثر شمولاً:

  1. @ExceptionHandler في وحدة تحكم (نطاق محلي)
  2. @RestControllerAdvice مع @ExceptionHandler (نطاق شامل)
  3. @ResponseStatus على استثناء مخصص

أفضل ممارسة هي @RestControllerAdvice الشامل الذي يركز كل إدارة الأخطاء.


س14. ما هو مشكلة N+1 في JPA وكيف نحلها؟​

الإجابة المتوقعة:

تحدث مشكلة N+1 عندما نقوم بتحميل كيان وJPA ينفذ N استعلامات إضافية لتحميل العلاقات:

1 استعلام لتحميل 100 قسم
+ 100 استعلام لتحميل الموظفين لكل قسم
= 101 استعلام بدلاً من 1 أو 2

الحلول:

  • JOIN FETCH في JPQL : @Query("SELECT d FROM Department d JOIN FETCH d.employees")
  • @EntityGraph : @EntityGraph(attributePaths = {"employees"})
  • @BatchSize : تحميل العلاقات على دفعات

س15. كيف نؤمن API REST باستخدام JWT؟​

الإجابة المتوقعة:

تدفق JWT:

1. يرسل العميل اسم المستخدم/كلمة المرور → POST /api/auth/login
2. يتحقق الخادم من بيانات الاعتماد
3. إذا كان صحيحًا → يولد JWT موقعة ويعيدها
4. يخزن العميل JWT
5. لكل طلب → Authorization: Bearer <token>
6. JwtAuthenticationFilter يستخرج ويحقق من صحة الرمز
7. إذا كان صحيحًا → يصادق المستخدم في SecurityContext

المكونات الرئيسية: JwtService (التوليد/التحقق)، JwtAuthenticationFilter (المرشح)، SecurityConfig (التكوين).


المستوى 3: أسئلة متقدمة​

س16. اشرح نمط IoC (Inversion of Control) في Spring.​

الإجابة المتوقعة:

IoC يعكس تدفق التحكم: بدلاً من أن يقوم الكود بإنشاء تبعياته، يقوم حاوية Spring بإنشائها وحقنها.

حاوية Spring (ApplicationContext) مسؤولة عن:

  1. إنشاء الكائنات (beans)
  2. تكوين الكائنات
  3. تجميع التبعيات
  4. إدارة دورة الحياة

حقن التبعيات (DI) هو الآلية الرئيسية لـ IoC في Spring.


س17. ما الفرق بين @Component، @Service، @Repository و @Controller؟​

الإجابة المتوقعة:

تقنيًا، الأربعة هم @Component. الفرق هو دلالي (الدور في البنية):

  • @Component : bean عام
  • @Service : منطق تجاري
  • @Repository : الوصول إلى البيانات + الترجمة التلقائية لاستثناءات SQL إلى استثناءات Spring
  • @Controller : إدارة طلبات الويب

استخدام التعليمة الصحيحة يساعد في القراءة ويسمح بمعالجات محددة (مثل ترجمة الاستثناءات لـ @Repository).


س18. كيف ننفذ الترقيم في Spring Data JPA؟​

الإجابة المتوقعة:

// Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByRole(Role role, Pageable pageable);
}

// Controller
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "name") String sortBy) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
return userRepository.findAll(pageable);
}

الـ Page<T> المعاد يحتوي على: المحتوى، رقم الصفحة، الحجم، إجمالي العناصر، عدد الصفحات.


س19. اشرح استراتيجيات الانتشار المختلفة لـ @Transactional.​

الإجابة المتوقعة:

الانتشارالسلوك
REQUIRED (افتراضي)ينضم إلى المعاملة الحالية أو ينشئ واحدة جديدة
REQUIRES_NEWينشئ دائمًا معاملة جديدة (يعلق الحالية)
SUPPORTSينضم إذا كانت موجودة، وإلا ينفذ بدون معاملة
NOT_SUPPORTEDينفذ دائمًا بدون معاملة (يعلق الحالية)
MANDATORYمعاملة موجودة مطلوبة، وإلا استثناء
NEVERلا معاملة، وإلا استثناء
NESTEDمعاملة متداخلة (نقطة حفظ)

حالة استخدام شائعة لـ REQUIRES_NEW : سجل التدقيق الذي يجب أن يستمر حتى إذا فشلت المعاملة الرئيسية.


س20. كيف نحسن أداء تطبيق Spring Boot؟​

الإجابة المتوقعة:

  1. JPA/Hibernate:

    • تجنب مشكلة N+1 (JOIN FETCH، EntityGraph)
    • استخدام @Transactional(readOnly = true) للقراءات
    • الإسقاطات DTO بدلاً من الكيانات الكاملة
    • الترقيم بشكل منهجي
  2. التخزين المؤقت:

    • @Cacheable مع Spring Cache (Redis، Caffeine)
    • التخزين المؤقت HTTP (ETag، Cache-Control)
  3. التكوين:

    • تجميع الاتصالات (HikariCP مُكون بشكل صحيح)
    • ضغط GZIP
    • ملفات تعريف محسنة للإنتاج
  4. البنية:

    • العمليات غير المتزامنة (@Async)
    • فهرسة قاعدة البيانات المناسبة
    • التحميل الكسول للعلاقات

س21. ما هو Spring Actuator وما هي النقاط النهائية المفيدة التي يوفرها؟​

الإجابة المتوقعة:

يوفر Spring Actuator نقاطًا نهائية للمراقبة والإدارة:

النقطة النهائيةالوصف
/actuator/healthحالة التطبيق (UP/DOWN)
/actuator/infoمعلومات عن التطبيق
/actuator/metricsمقاييس (الذاكرة، وحدة المعالجة المركزية، الطلبات)
/actuator/envمتغيرات البيئة
/actuator/beansقائمة بجميع الـ beans
/actuator/mappingsجميع النقاط النهائية REST
/actuator/loggersتكوين المسجلات
/actuator/prometheusمقاييس بتنسيق Prometheus

في الإنتاج، يجب تأمين هذه النقاط النهائية وعدم كشف سوى /health و /info علنًا.


س22. اشرح دورة حياة bean في Spring.​

الإجابة المتوقعة:

1. الإنشاء (المُنشئ)
2. حقن التبعيات (@Autowired)
3. واجهات Aware (BeanNameAware، ApplicationContextAware...)
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. طريقة init مخصصة
8. BeanPostProcessor.postProcessAfterInitialization()
9. ══════ bean جاهز للاستخدام ══════
10. @PreDestroy
11. DisposableBean.destroy()
12. طريقة destroy مخصصة

في الممارسة، نستخدم بشكل أساسي @PostConstruct و @PreDestroy.


س23. كيف ننفذ نمط CQRS مبسط مع Spring Boot؟​

الإجابة المتوقعة:

CQRS (Command Query Responsibility Segregation) يفصل بين عمليات القراءة والكتابة:

// Command (كتابة)
@Service
@Transactional
public class UserCommandService {
public User create(CreateUserCommand cmd) { ... }
public void update(UpdateUserCommand cmd) { ... }
public void delete(Long id) { ... }
}

// Query (قراءة)
@Service
@Transactional(readOnly = true)
public class UserQueryService {
public UserDto findById(Long id) { ... }
public Page<UserDto> findAll(Pageable page) { ... }
}

يسمح ذلك بتحسين القراءات والكتابات بشكل منفصل (مثل: الإسقاطات DTO للقراءات، التحقق المعقد للكتابات).


أسئلة سلوكية / سيناريوهات​

س24. يجب عليك تصميم API REST لنظام تجارة إلكترونية. ما هي النقاط النهائية التي تنشئها؟​

الإجابة المتوقعة:

المنتجات:
GET /api/products → قائمة مرقمة
GET /api/products/{id} → تفاصيل منتج
POST /api/products → إنشاء (ADMIN)
PUT /api/products/{id} → تعديل (ADMIN)
DELETE /api/products/{id} → حذف (ADMIN)

الطلبات:
POST /api/orders → تقديم طلب
GET /api/orders → طلباتي
GET /api/orders/{id} → تفاصيل طلب
PATCH /api/orders/{id} → تعديل الحالة (ADMIN)

المصادقة:
POST /api/auth/register → تسجيل
POST /api/auth/login → تسجيل الدخول (يعيد JWT)
POST /api/auth/refresh → تحديث الرمز

السلة:
GET /api/cart → سلتي
POST /api/cart/items → إضافة إلى السلة
DELETE /api/cart/items/{id} → إزالة من السلة

س25. تطبيق Spring Boot الخاص بك بطيء في الإنتاج. كيف تشخص المشكلة؟​

الإجابة المتوقعة:

  1. Actuator metrics : تحقق من /actuator/metrics/http.server.requests لتحديد النقاط النهائية البطيئة
  2. السجلات : تفعيل logging.level.org.hibernate.SQL=DEBUG لرؤية استعلامات SQL
  3. مشكلة N+1 : تحقق من عدد الاستعلامات باستخدام spring.jpa.show-sql=true
  4. تجميع الاتصالات : تحقق من مقاييس HikariCP (hikaricp.connections.active)
  5. التحليل : VisualVM أو JFR (Java Flight Recorder)
  6. فهرسة قاعدة البيانات : تحليل الاستعلامات البطيئة باستخدام EXPLAIN ANALYZE
  7. الذاكرة : تحقق من جامع القمامة وحجم الكومة

قائمة التحقق من التحضير​

قبل مقابلتك، تأكد من قدرتك على:

  • شرح IoC و DI مع مثال ملموس
  • وصف بنية الطبقات لتطبيق Spring Boot
  • كتابة CRUD كامل (Controller → Service → Repository)
  • شرح JWT وتدفق المصادقة
  • التحدث عن مشاريعك الشخصية في Spring Boot
  • وصف كيفية إدارة الاستثناءات
  • شرح الفرق بين التعليمات الرئيسية
  • التحدث عن Docker و CI/CD مع Spring Boot
  • معرفة أساسيات الترقيم والفرز
  • معرفة كيفية تشخيص مشاكل الأداء

⬅️ العودة إلى الصفحة الرئيسية