## الدليل الشامل لإطار عمل Spring
تمت كتابة هذه المدونة بمساعدة ChatGPT-4o.
جدول المحتويات
- مقدمة
- إطار عمل Spring Boot
- إدارة البيانات مع Spring
- بناء خدمات RESTful
- البريد الإلكتروني، المهام، والجدولة
- الاختبار في Spring
- المراقبة والإدارة
- موضوعات متقدمة
- الخاتمة
مقدمة
Spring هو أحد أكثر الأطر شيوعًا لبناء تطبيقات على مستوى المؤسسات باستخدام لغة Java. يوفر دعمًا بنيويًا شاملاً لتطوير تطبيقات Java. في هذه المدونة، سنغطي جوانب مختلفة من نظام Spring البيئي، بما في ذلك Spring Boot، وإدارة البيانات، وبناء خدمات RESTful، والجدولة، والاختبار، والميزات المتقدمة مثل Spring Advice API.
إطار عمل Spring Boot
Spring Boot هو إطار عمل مفتوح المصدر يعتمد على لغة Java، مصمم لتبسيط عملية تطوير تطبيقات Spring. يوفر Spring Boot بيئة عمل سريعة وسهلة التكوين، مما يسمح للمطورين بإنشاء تطبيقات قائمة بذاتها بسرعة وسهولة. يتميز Spring Boot بدمج العديد من المكتبات والأدوات التي تسهل عملية التطوير، مثل Tomcat المدمج، وإدارة التبعيات عبر Maven أو Gradle، والتكوين التلقائي للتطبيقات.
المميزات الرئيسية لـ Spring Boot:
- سهولة التكوين: يوفر Spring Boot تكوينًا تلقائيًا للعديد من الإعدادات، مما يقلل من الحاجة إلى تكوين يدوي.
- تطبيقات قائمة بذاتها: يمكنك تشغيل تطبيقات Spring Boot كتطبيقات مستقلة دون الحاجة إلى خوادم خارجية.
- إدارة التبعيات: يدعم Spring Boot إدارة التبعيات عبر Maven وGradle، مما يسهل عملية إضافة المكتبات المطلوبة.
- مراقبة وصيانة: يوفر Spring Boot أدوات لمراقبة وصيانة التطبيقات، مثل Actuator.
- تكامل مع Spring Ecosystem: يتكامل Spring Boot بسلاسة مع باقي إطار عمل Spring، مثل Spring MVC وSpring Data وSpring Security.
مثال بسيط لتطبيق Spring Boot:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
@GetMapping("/")
public String hello() {
return "Hello, World!";
}
}
في هذا المثال، يتم إنشاء تطبيق Spring Boot بسيط يعرض رسالة “Hello, World!” عند الوصول إلى المسار الرئيسي (/
).
كيفية تشغيل التطبيق:
- قم بتنزيل المشروع أو إنشائه باستخدام Spring Initializr.
- افتح المشروع في بيئة التطوير الخاصة بك (مثل IntelliJ IDEA أو Eclipse).
- قم بتشغيل التطبيق عن طريق تنفيذ الأمر
mvn spring-boot:run
في سطر الأوامر. - افتح المتصفح واذهب إلى
http://localhost:8080
لرؤية الرسالة “Hello, World!”.
Spring Boot يعد خيارًا مثاليًا لتطوير تطبيقات الويب والخدمات المصغرة (Microservices) بسرعة وكفاءة.
البدء مع Spring Boot
Spring Boot يجعل من السهل إنشاء تطبيقات Spring قائمة بذاتها وجاهزة للإنتاج. يأخذ وجهة نظر محددة حول منصة Spring والمكتبات الخارجية، مما يسمح لك بالبدء بأقل قدر من التهيئة.
- الإعداد الأولي: ابدأ بإنشاء مشروع Spring Boot جديد باستخدام Spring Initializr. يمكنك اختيار التبعيات التي تحتاجها، مثل Spring Web، وSpring Data JPA، وSpring Boot Actuator.
- الشرح التوضيحي (Annotations): تعرف على الشرح التوضيحي الرئيسي مثل
@SpringBootApplication
، والذي هو مزيج من@Configuration
، و@EnableAutoConfiguration
، و@ComponentScan
. - الخادم المدمج: يستخدم Spring Boot خوادم مدمجة مثل Tomcat، أو Jetty، أو Undertow لتشغيل تطبيقك، لذلك لا تحتاج إلى نشر ملفات WAR على خادم خارجي.
حقن التبعيات (Dependency Injection)
حقن التبعيات (Dependency Injection أو DI) هو مبدأ أساسي في إطار عمل Spring. يسمح بإنشاء مكونات ذات اقتران ضعيف، مما يجعل الكود الخاص بك أكثر نمطية وأسهل في الاختبار.
@Autowired
: تُستخدم هذه الشرحة لحقن التبعيات تلقائيًا. يمكن تطبيقها على المُنشئات (constructors)، الحقول (fields)، والطرق (methods). ستقوم ميزة حقن التبعيات في Spring بحل وحقن الحبوب (beans) المتعاونة تلقائيًا في حبتك (bean).
مثال على حقن الحقول:
@Component
public class UserService {
@Autowired
private UserRepository userRepository;
// طرق الأعمال
}
مثال على حقن المُنشئ:
@Component
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// طرق الأعمال
}
مثال على حقن الأسلوب (Method Injection):
@Component
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
// طرق الأعمال
}
-
@Component
,@Service
,@Repository
: هذه هي تخصيصات لـ@Component
annotation، تُستخدم للإشارة إلى أن الفصل هو Spring bean. كما أنها تعمل كتلميحات لدور الفصل الذي تم تعليقه. -
@Component
: هذا نمط عام لأي مكون يتم إدارته بواسطة Spring. يمكن استخدامه لوضع علامة على أي فئة كـ bean في Spring.
مثال:
@Component
public class EmailValidator {
public boolean isValid(String email) {
// منطق التحقق
return true;
}
}
@Service
: هذه الشرح هي تخصيص لـ@Component
وتُستخدم لتمييز الفئة كخدمة. تُستخدم عادةً في طبقة الخدمة، حيث يتم تنفيذ منطق الأعمال.
مثال:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
ترجمة الكود إلى العربية:
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
ملاحظة: الكود يبقى كما هو لأنه مكتوب بلغة برمجية (Java) ولا يتم ترجمته. الترجمة تكون فقط للنصوص التوضيحية أو الشروحات المرافقة للكود.
-
@Repository
: هذه التعليمة هي أيضًا تخصيص للتعليمة@Component
. تُستخدم للإشارة إلى أن الفئة توفر آلية لتخزين واسترجاع والبحث وتحديث وحذف الكائنات. كما تقوم بترجمة استثناءات الاستمرارية إلى التسلسل الهرمي لاستثناءات الوصول إلى البيانات في Spring.مثال:
@Repository public interface UserRepository extends JpaRepository<User, Long> { // طرق الاستعلام المخصصة }
هذه التعليقات التوضيحية تجعل تكوين Spring الخاص بك أكثر قابلية للقراءة وإيجازًا، وتساعد إطار عمل Spring في إدارة وربط التبعيات بين الحبوب (beans) المختلفة.
الأحداث في Spring
في إطار عمل Spring، تُعتبر الأحداث (Events) وسيلة للتواصل بين مكونات التطبيق بطريقة غير مباشرة. تسمح هذه الآلية للمكونات بإرسال إشعارات حول حدوث شيء ما، بينما يمكن لمكونات أخرى الاستماع إلى هذه الإشعارات والاستجابة لها. يتم تنفيذ هذا النموذج باستخدام ApplicationEvent
و ApplicationListener
.
كيفية عمل الأحداث في Spring
-
إنشاء حدث مخصص: يمكنك إنشاء حدث مخصص عن طريق توسيع الفئة
ApplicationEvent
.public class CustomEvent extends ApplicationEvent { private String message; public CustomEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; } }
-
نشر الحدث: يمكن نشر الحدث باستخدام
ApplicationEventPublisher
.@Autowired private ApplicationEventPublisher publisher; public void publishCustomEvent(final String message) { CustomEvent customEvent = new CustomEvent(this, message); publisher.publishEvent(customEvent); }
-
الاستماع إلى الحدث: يمكنك الاستماع إلى الحدث عن طريق تنفيذ واجهة
ApplicationListener
.@Component public class CustomEventListener implements ApplicationListener<CustomEvent> { @Override public void onApplicationEvent(CustomEvent event) { System.out.println("Received custom event - " + event.getMessage()); } }
استخدام الأحداث في Spring
تُستخدم الأحداث في Spring لتحقيق فصل المهام (Separation of Concerns) وتحسين قابلية الصيانة. على سبيل المثال، يمكن استخدامها لإرسال إشعارات عبر البريد الإلكتروني بعد تسجيل مستخدم جديد، أو لتحديث ذاكرة التخزين المؤقت بعد تغيير البيانات.
مثال عملي
لنفترض أن لديك تطبيقًا لإدارة المستخدمين، وتريد إرسال بريد إلكتروني ترحيبي عند تسجيل مستخدم جديد.
-
إنشاء حدث تسجيل المستخدم:
public class UserRegisteredEvent extends ApplicationEvent { private String email; public UserRegisteredEvent(Object source, String email) { super(source); this.email = email; } public String getEmail() { return email; } }
-
نشر الحدث عند تسجيل المستخدم:
@Service public class UserService { @Autowired private ApplicationEventPublisher publisher; public void registerUser(String email) { // Logic to register user publisher.publishEvent(new UserRegisteredEvent(this, email)); } }
-
الاستماع إلى الحدث وإرسال البريد الإلكتروني:
@Component public class EmailService implements ApplicationListener<UserRegisteredEvent> { @Override public void onApplicationEvent(UserRegisteredEvent event) { sendWelcomeEmail(event.getEmail()); } private void sendWelcomeEmail(String email) { // Logic to send email System.out.println("Sending welcome email to " + email); } }
بهذه الطريقة، يتم فصل منطق إرسال البريد الإلكتروني عن منطق تسجيل المستخدم، مما يجعل الكود أكثر تنظيماً وسهولة في الصيانة.
تتيح لك آلية الأحداث في Spring إنشاء الأحداث في التطبيق والاستماع إليها.
- الأحداث المخصصة: يمكنك إنشاء أحداث مخصصة عن طريق توسيع الفئة
ApplicationEvent
. على سبيل المثال:public class MyCustomEvent extends ApplicationEvent { private String message;
public MyCustomEvent(Object source, String message) {
super(source);
this.message = message;
}
تمت ترجمة الكود أعلاه إلى:
public MyCustomEvent(Object source, String message) {
super(source);
this.message = message;
}
في هذا الكود، يتم تعريف مُنشئ (constructor) لفئة MyCustomEvent
يأخذ كمعاملات Object source
و String message
. يتم استدعاء المُنشئ الأساسي (super constructor) باستخدام super(source)
، ثم يتم تعيين القيمة الممررة للمعامل message
إلى المتغير this.message
.
public String getMessage() {
return message;
}
}
- مستمعو الأحداث: استخدم
@EventListener
أو قم بتنفيذApplicationListener
للتعامل مع الأحداث. على سبيل المثال:@Component public class MyEventListener {
@EventListener
public void handleMyCustomEvent(MyCustomEvent event) {
System.out.println("تم استقبال حدث Spring مخصص - " + event.getMessage());
}
- نشر الأحداث: يمكنك نشر الأحداث باستخدام
ApplicationEventPublisher
. على سبيل المثال:@Component public class MyEventPublisher { @Autowired private ApplicationEventPublisher applicationEventPublisher;
public void publishCustomEvent(final String message) {
System.out.println("جاري نشر حدث مخصص. ");
MyCustomEvent customEvent = new MyCustomEvent(this, message);
applicationEventPublisher.publishEvent(customEvent);
}
}
إدارة البيانات باستخدام Spring
Spring Data JDBC
Spring Data JDBC هي جزء من مشروع Spring Data الذي يهدف إلى تبسيط الوصول إلى قواعد البيانات العلائقية باستخدام JDBC. يوفر Spring Data JDBC طبقة تجريدية فوق JDBC التقليدي، مما يجعل من السهل تنفيذ عمليات CRUD (إنشاء، قراءة، تحديث، حذف) دون الحاجة إلى كتابة الكثير من الكود المتكرر.
المميزات الرئيسية:
- تبسيط الكود: يقلل من الحاجة إلى كتابة كود JDBC تقليدي متكرر.
- دعم الكيانات البسيطة: يدعم الكيانات البسيطة التي تعكس جداول قاعدة البيانات.
- استعلامات مخصصة: يسمح بكتابة استعلامات SQL مخصصة بسهولة.
- تكامل مع Spring: يتكامل بسلاسة مع إطار عمل Spring، مما يسهل إدارة الكيانات والتبعيات.
مثال بسيط:
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
@Table("users")
public class User {
@Id
private Long id;
private String name;
private String email;
// Getters and Setters
}
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> {
User findByEmail(String email);
}
في هذا المثال، يتم تعريف كيان User
الذي يعكس جدول users
في قاعدة البيانات. يتم استخدام UserRepository
للوصول إلى البيانات وتنفيذ عمليات CRUD بسهولة.
الخلاصة:
Spring Data JDBC هو أداة قوية لتبسيط الوصول إلى قواعد البيانات العلائقية باستخدام JDBC، مع الحفاظ على البساطة والمرونة.
يوفر Spring Data JDBC وصولًا بسيطًا وفعالًا إلى JDBC.
- المستودعات (Repositories): قم بتعريف المستودعات لإجراء عمليات CRUD (إنشاء، قراءة، تحديث، حذف). على سبيل المثال:
public interface UserRepository extends CrudRepository<User, Long> { }
- الاستعلامات: استخدم التعليقات التوضيحية مثل
@Query
لتحديد استعلامات مخصصة. على سبيل المثال:@Query("SELECT * FROM users WHERE username = :username") User findByUsername(String username);
Spring Data JPA
Spring Data JPA هو جزء من مشروع Spring Data الذي يهدف إلى تبسيط تطوير تطبيقات Java التي تعتمد على تقنيات الوصول إلى البيانات. يوفر Spring Data JPA طبقة تجريدية فوق JPA (Java Persistence API)، مما يسهل عملية تنفيذ عمليات الوصول إلى البيانات دون الحاجة إلى كتابة الكثير من الكود المتكرر.
الميزات الرئيسية لـ Spring Data JPA
-
تقليل الكود المتكرر: يوفر Spring Data JPA واجهات برمجية جاهزة للاستخدام للتعامل مع الكيانات (Entities) وعمليات CRUD (إنشاء، قراءة، تحديث، حذف) دون الحاجة إلى كتابة الكود يدويًا.
-
الاستعلامات المخصصة: يمكنك كتابة استعلامات مخصصة باستخدام لغة JPQL (Java Persistence Query Language) أو عن طريق استخدام أسماء الطرق في الواجهات البرمجية.
-
التكامل مع Spring: Spring Data JPA يتكامل بسلاسة مع إطار عمل Spring، مما يسمح باستخدام ميزات مثل إدارة المعاملات (Transaction Management) وحقن التبعيات (Dependency Injection).
-
الدعم للاستعلامات الديناميكية: يمكنك إنشاء استعلامات ديناميكية باستخدام
Specification
وCriteria API
. -
التقسيم (Pagination) والفرز (Sorting): يوفر Spring Data JPA دعمًا مدمجًا للتقسيم والفرز، مما يسهل التعامل مع مجموعات كبيرة من البيانات.
مثال بسيط
لنفترض أن لديك كيان User
وتريد تنفيذ عمليات CRUD عليه. يمكنك إنشاء واجهة برمجية تمتد JpaRepository
كما يلي:
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
// يمكنك إضافة طرق مخصصة هنا
}
بعد ذلك، يمكنك استخدام هذه الواجهة في خدمة (Service) أو وحدة تحكم (Controller) للتعامل مع البيانات:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
public User saveUser(User user) {
return userRepository.save(user);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
الخلاصة
Spring Data JPA يوفر طريقة فعالة وسهلة للتعامل مع قواعد البيانات في تطبيقات Java باستخدام Spring. بفضل طبقة التجريد التي يوفرها، يمكنك التركيز على كتابة منطق الأعمال بدلاً من القلق بشأن تفاصيل تنفيذ الوصول إلى البيانات.
Spring Data JPA يجعل من السهل تنفيذ مستودعات تعتمد على JPA.
- تعيين الكيانات: قم بتعريف الكيانات باستخدام
@Entity
وقم بتعيينها إلى جداول قاعدة البيانات. على سبيل المثال:@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; // getters and setters }
- المستودعات (Repositories): أنشئ واجهات المستودعات عن طريق توسيع
JpaRepository
. على سبيل المثال:public interface UserRepository extends JpaRepository<User, Long> { }
- طرق الاستعلام: استخدم طرق الاستعلام لإجراء عمليات قاعدة البيانات. على سبيل المثال:
List<User> findByUsername(String username);
Spring Data Redis
Spring Data Redis هو جزء من مشروع Spring Data الذي يهدف إلى تبسيط الوصول إلى قواعد البيانات NoSQL، وتحديدًا Redis. Redis هو مخزن بيانات مفتوح المصدر يعتمد على الذاكرة، ويستخدم كقاعدة بيانات، وذاكرة تخزين مؤقت، ووسيط للرسائل. يوفر Spring Data Redis طبقة تجريدية تسمح للمطورين بالتفاعل مع Redis بسهولة باستخدام واجهات برمجية مألوفة في Spring.
الميزات الرئيسية
- التكامل السلس مع Spring: يمكن دمج Spring Data Redis بسهولة مع تطبيقات Spring الأخرى، مما يوفر تجربة تطوير متسقة.
- دعم للأنواع المختلفة من البيانات: يدعم Spring Data Redis أنواعًا مختلفة من البيانات مثل Strings, Hashes, Lists, Sets, و Sorted Sets.
- التعامل مع الاتصالات: يوفر إدارة اتصالات Redis عبر
RedisConnectionFactory
، مما يسهل تكوين وإدارة الاتصالات. - دعم للتعامل مع الكيانات: يمكن تعيين الكيانات (Entities) إلى هياكل بيانات Redis باستخدام
RedisTemplate
أوRepository
interfaces. - دعم للاستعلامات: يوفر دعمًا للاستعلامات باستخدام معايير بسيطة، مما يسمح بالبحث عن البيانات المخزنة في Redis.
مثال بسيط
فيما يلي مثال بسيط يوضح كيفية تكوين واستخدام Spring Data Redis في تطبيق Spring Boot:
@SpringBootApplication
public class RedisExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RedisExampleApplication.class, args);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
}
في هذا المثال، نقوم بتكوين RedisTemplate
واستخدامه لتخزين واسترجاع البيانات من Redis.
الخلاصة
Spring Data Redis يوفر طريقة قوية وسهلة للتفاعل مع Redis في تطبيقات Spring. سواء كنت تقوم ببناء تطبيق جديد أو تحسين تطبيق موجود، فإن Spring Data Redis يمكن أن يساعدك على تحقيق أهدافك بفعالية.
يوفر Spring Data Redis البنية التحتية للوصول إلى البيانات المعتمدة على Redis.
- RedisTemplate: استخدم
RedisTemplate
للتفاعل مع Redis. على سبيل المثال:@Autowired private RedisTemplate<String, Object> redisTemplate;
public void save(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
الترجمة:
public void save(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
في هذه الدالة، يتم حفظ قيمة معينة (value
) في قاعدة بيانات Redis باستخدام مفتاح محدد (key
). يتم استخدام redisTemplate
للوصول إلى عمليات Redis وحفظ القيمة.
public Object find(String key) {
return redisTemplate.opsForValue().get(key);
}
تمت ترجمة الكود أعلاه إلى:
public Object find(String key) {
return redisTemplate.opsForValue().get(key);
}
ملاحظة: الكود لم يتغير لأنه مكتوب بلغة برمجية (Java) ولا يتم ترجمته.
- المستودعات: قم بإنشاء مستودعات Redis باستخدام
@Repository
. على سبيل المثال:@Repository public interface RedisRepository extends CrudRepository<RedisEntity, String> { }
المعاملات ودعم DAO
يُسهل Spring إدارة المعاملات (Transactions) ودعم DAO (كائن الوصول إلى البيانات).
- إدارة المعاملات: استخدم
@Transactional
لإدارة المعاملات. على سبيل المثال:@Transactional public void saveUser(User user) { userRepository.save(user); }
- نمط DAO: قم بتنفيذ نمط DAO لفصل منطق التخزين. على سبيل المثال:
public class UserDao { @Autowired private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
return jdbcTemplate.queryForObject("SELECT * FROM users WHERE id = ?", new Object[]{id}, new UserRowMapper());
}
}
ترجمة الكود إلى العربية:
public User findById(Long id) {
return jdbcTemplate.queryForObject("SELECT * FROM users WHERE id = ?", new Object[]{id}, new UserRowMapper());
}
}
ملاحظة: الكود يبقى كما هو لأنه مكتوب بلغة برمجية (Java) ولا يتم ترجمته.
JDBC و ORM
JDBC (Java Database Connectivity) هي واجهة برمجة تطبيقات (API) تُستخدم في لغة Java للتفاعل مع قواعد البيانات. تسمح JDBC للتطبيقات بتنفيذ استعلامات SQL وإدارة البيانات في قواعد البيانات العلائقية. توفر JDBC مجموعة من الواجهات والفئات التي تمكن المطورين من الاتصال بقاعدة البيانات، وإرسال استعلامات SQL، ومعالجة النتائج.
ORM (Object-Relational Mapping) هي تقنية تُستخدم لتحويل البيانات بين نظام أنواع غير متوافق في لغات البرمجة الموجهة للكائنات (مثل Java) وقواعد البيانات العلائقية. تُسهل ORM على المطورين العمل مع قواعد البيانات باستخدام الكائنات بدلاً من كتابة استعلامات SQL مباشرة. من أشهر أدوات ORM في Java هي Hibernate و JPA (Java Persistence API).
الفرق بين JDBC و ORM:
- JDBC: يتطلب كتابة استعلامات SQL يدويًا وإدارة الاتصالات والنتائج بشكل صريح.
- ORM: يُخفف من الحاجة إلى كتابة استعلامات SQL يدويًا عن طريق تعيين الكائنات إلى جداول قاعدة البيانات تلقائيًا.
مثال بسيط باستخدام JDBC:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcExample {
public static void main(String[] args) {
try {
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
مثال بسيط باستخدام ORM (Hibernate):
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateExample {
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
User user = new User();
user.setUsername("john_doe");
session.save(user);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
في المثالين أعلاه، يمكنك أن ترى كيف أن ORM يُبسط عملية التفاعل مع قاعدة البيانات مقارنة بـ JDBC.
يوفر Spring دعمًا شاملاً لـ JDBC و ORM (تعيين الكائنات إلى العلاقات).
- JdbcTemplate: تبسيط عمليات JDBC باستخدام
JdbcTemplate
. على سبيل المثال:@Autowired private JdbcTemplate jdbcTemplate;
public List<User> findAll() {
return jdbcTemplate.query("SELECT * FROM users", new UserRowMapper());
}
ترجمة الكود أعلاه إلى العربية:
public List<User> findAll() {
return jdbcTemplate.query("SELECT * FROM users", new UserRowMapper());
}
في هذا الكود، يتم تعريف دالة findAll
التي تقوم بإرجاع قائمة من الكائنات من نوع User
. يتم استخدام jdbcTemplate.query
لتنفيذ استعلام SQL يقوم بجلب جميع السجلات من جدول users
، ويتم تحويل النتائج إلى كائنات User
باستخدام UserRowMapper
.
- Hibernate: قم بدمج Hibernate مع Spring لدعم ORM. على سبيل المثال:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; // getters and setters }
بناء خدمات RESTful
عملاء REST في Spring
يوفر Spring عدة خيارات لإنشاء عملاء REST للتفاعل مع خدمات الويب. فيما يلي بعض الأدوات الرئيسية التي يمكن استخدامها:
-
RestTemplate:
RestTemplate
هو أداة كلاسيكية في Spring لتنفيذ طلبات HTTP. إنه متزامن (synchronous) ويوفر واجهة برمجية بسيطة لإرسال الطلبات واستقبال الاستجابات.RestTemplate restTemplate = new RestTemplate(); String url = "https://api.example.com/resource"; String response = restTemplate.getForObject(url, String.class); System.out.println(response);
-
WebClient:
WebClient
هو بديل غير متزامن (asynchronous) لـRestTemplate
ويعتمد على Reactive Programming. إنه مناسب للتطبيقات التي تحتاج إلى التعامل مع طلبات غير متزامنة.WebClient webClient = WebClient.create("https://api.example.com"); Mono<String> response = webClient.get() .uri("/resource") .retrieve() .bodyToMono(String.class); response.subscribe(System.out::println);
-
RestClient:
RestClient
هو واجهة برمجية جديدة في Spring 6 تهدف إلى تبسيط إنشاء عملاء REST. إنه يوفر واجهة برمجية أكثر حداثة ومرونة.RestClient restClient = RestClient.create(); String response = restClient.get() .uri("https://api.example.com/resource") .retrieve() .body(String.class); System.out.println(response);
-
Feign Client:
Feign
هو مكتبة تسمح بإنشاء عملاء REST بطريقة إعلانية (declarative). يمكن استخدامها مع Spring Cloud لإنشاء عملاء REST بسهولة.@FeignClient(name = "exampleClient", url = "https://api.example.com") public interface ExampleClient { @GetMapping("/resource") String getResource(); }
-
RestEasy Client:
RestEasy
هو مكتبة أخرى يمكن استخدامها لإنشاء عملاء REST. إنها توفر واجهة برمجية قوية لتنفيذ طلبات HTTP.ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("https://api.example.com/resource"); String response = target.request().get(String.class); System.out.println(response);
اختيار الأداة المناسبة يعتمد على احتياجات التطبيق الخاص بك. إذا كنت تعمل في بيئة متزامنة، فقد يكون RestTemplate
خيارًا جيدًا. أما إذا كنت بحاجة إلى معالجة غير متزامنة، فإن WebClient
هو الخيار الأفضل.
Spring يجعل من السهل بناء عملاء RESTful.
- RestTemplate: استخدم
RestTemplate
لإجراء طلبات HTTP. على سبيل المثال:@Autowired private RestTemplate restTemplate;
public String getUserInfo(String userId) {
return restTemplate.getForObject("https://api.example.com/users/" + userId, String.class);
}
تمت ترجمة الكود أعلاه إلى:
public String getUserInfo(String userId) {
return restTemplate.getForObject("https://api.example.com/users/" + userId, String.class);
}
ملاحظة: الكود لم يتغير لأنه مكتوب بلغة برمجية (Java) ولا يتم ترجمته.
- WebClient: استخدم
WebClient
التفاعلي للطلبات غير المتزامنة. على سبيل المثال:@Autowired private WebClient.Builder webClientBuilder;
public Mono<String> getUserInfo(String userId) {
return webClientBuilder.build()
.get()
.uri("https://api.example.com/users/" + userId)
.retrieve()
.bodyToMono(String.class);
}
FeignClient
FeignClient هي مكتبة تُستخدم في تطبيقات Spring Cloud لتبسيط عملية استدعاء خدمات RESTful. تُوفر واجهة برمجية سهلة الاستخدام لإنشاء عميل HTTP، مما يسمح للمطورين بالتفاعل مع خدمات الويب دون الحاجة إلى كتابة كود HTTP يدويًا. باستخدام FeignClient، يمكنك تعريف واجهة برمجية مع التعليقات التوضيحية (annotations) التي تصف كيفية استدعاء خدمة معينة، وتقوم المكتبة بإنشاء التنفيذ المناسب تلقائيًا.
مثال بسيط لاستخدام FeignClient:
@FeignClient(name = "example-service", url = "https://api.example.com")
public interface ExampleServiceClient {
@GetMapping("/example-endpoint")
String getExampleData();
}
في هذا المثال، يتم تعريف واجهة برمجية ExampleServiceClient
التي تستخدم التعليق التوضيحي @FeignClient
لتحديد اسم الخدمة وعنوان URL الخاص بها. الطريقة getExampleData
تستخدم التعليق التوضيحي @GetMapping
لتحديد نقطة النهاية التي سيتم استدعاؤها. عند استدعاء هذه الطريقة، سيقوم FeignClient تلقائيًا بإجراء طلب HTTP GET إلى https://api.example.com/example-endpoint
وإرجاع النتيجة.
FeignClient يدعم أيضًا العديد من الميزات المتقدمة مثل التوازن التلقائي للتحميل (load balancing)، والتعامل مع الأخطاء، والتشفير، وغيرها.
Feign هو عميل خدمة ويب تصريحي.
- الإعداد: أضف Feign إلى مشروعك وأنشئ واجهات مع التعليقات التوضيحية باستخدام
@FeignClient
. على سبيل المثال:@FeignClient(name = "user-service", url = "https://api.example.com") public interface UserServiceClient { @GetMapping("/users/{id}") String getUserInfo(@PathVariable("id") String userId); }
- التهيئة: تخصيص عملاء Feign باستخدام المُعترضات (interceptors) وفك تشفير الأخطاء (error decoders). على سبيل المثال:
@Bean public RequestInterceptor requestInterceptor() { return requestTemplate -> requestTemplate.header("Authorization", "Bearer token"); }
البريد الإلكتروني، المهام، والجدولة
دعم البريد الإلكتروني
يوفر Spring دعمًا لإرسال البريد الإلكتروني.
- JavaMailSender: استخدم
JavaMailSender
لإرسال البريد الإلكتروني. على سبيل المثال:@Autowired private JavaMailSender mailSender;
public void sendEmail(String to, String subject, String body) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(body);
mailSender.send(message);
}
- MimeMessage: إنشاء رسائل بريد إلكتروني غنية بالمرفقات ومحتوى HTML. على سبيل المثال:
@Autowired private JavaMailSender mailSender;
public void sendRichEmail(String to, String subject, String body, File attachment) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(body, true);
helper.addAttachment(attachment.getName(), attachment);
mailSender.send(message);
}
تنفيذ المهام والجدولة
دعم Spring لتنفيذ المهام وجدولتها يجعل من السهل تشغيل المهام.
@Scheduled
: جدولة المهام باستخدام@Scheduled
. على سبيل المثال:@Scheduled(fixedRate = 5000) public void performTask() { System.out.println("Scheduled task running every 5 seconds"); }
- المهام غير المتزامنة: تشغيل المهام بشكل غير متزامن باستخدام
@Async
. على سبيل المثال:@Async public void performAsyncTask() { System.out.println("Async task running in background"); }
الاختبار في Spring
عند العمل مع إطار عمل Spring، يعد الاختبار جانبًا مهمًا لضمان جودة الكود وسلوك التطبيق كما هو متوقع. يوفر Spring مجموعة من الأدوات والمكتبات التي تسهل كتابة الاختبارات للفئات والمكونات المختلفة.
أنواع الاختبارات في Spring
-
Unit Testing (اختبار الوحدة): يتم اختبار كل وحدة (عادةً ما تكون كلاس) بشكل منفصل عن باقي التطبيق. يمكن استخدام إطار عمل مثل JUnit لكتابة هذه الاختبارات.
-
Integration Testing (اختبار التكامل): يتم اختبار تفاعل عدة وحدات معًا للتأكد من أنها تعمل بشكل صحيح معًا. يوفر Spring إمكانية اختبار تكامل المكونات مع بعضها البعض.
-
End-to-End Testing (اختبار من البداية إلى النهاية): يتم اختبار التطبيق بأكمله من البداية إلى النهاية، عادةً باستخدام أدوات مثل Selenium أو Spring Boot Test.
أدوات الاختبار في Spring
- JUnit: إطار عمل شائع لكتابة الاختبارات في Java.
- Mockito: مكتبة لإنشاء كائنات وهمية (Mocks) لاختبار التفاعلات بين الكائنات.
- Spring Test: يوفر Spring إطار عمل خاص للاختبار يتكامل مع JUnit ويوفر ميزات مثل تحميل سياق التطبيق (ApplicationContext) للاختبارات.
مثال على اختبار وحدة باستخدام JUnit و Mockito
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@BeforeEach
public void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testGetData() {
when(myRepository.findData()).thenReturn("Mocked Data");
String result = myService.getData();
assertEquals("Mocked Data", result);
verify(myRepository, times(1)).findData();
}
}
في هذا المثال، يتم اختبار MyService
باستخدام MyRepository
ككائن وهمي (Mock). يتم التحقق من أن getData()
يعيد القيمة المتوقعة وأن findData()
يتم استدعاؤها مرة واحدة فقط.
اختبار التكامل باستخدام Spring Boot Test
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
public class MyControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetEndpoint() throws Exception {
mockMvc.perform(get("/my-endpoint"))
.andExpect(status().isOk())
.andExpect(content().string("Expected Response"));
}
}
في هذا المثال، يتم اختبار نقطة نهاية (endpoint) في MyController
باستخدام MockMvc
للتحقق من أن الاستجابة هي كما هو متوقع.
الخلاصة
الاختبار في Spring هو عملية أساسية لضمان جودة التطبيق وسلوكه الصحيح. باستخدام الأدوات المناسبة مثل JUnit و Mockito و Spring Test، يمكنك كتابة اختبارات فعالة تغطي مختلف جوانب التطبيق.
الاختبار باستخدام Mockito
Mockito هي مكتبة شائعة في عالم Java تُستخدم لإنشاء كائنات وهمية (mocks) في اختبارات الوحدة. تُسهل Mockito عملية اختبار الكود عن طريق السماح لك بمحاكاة سلوك الكائنات المعقدة أو الخارجية، مما يجعل الاختبارات أكثر تركيزًا وسرعة.
لماذا نستخدم Mockito؟
- عزل الكود: تسمح لك Mockito باختبار الكود بشكل معزول عن التبعيات الخارجية مثل قواعد البيانات أو خدمات الويب.
- التحكم في السلوك: يمكنك تحديد السلوك المتوقع للكائنات الوهمية، مما يسمح لك باختبار سيناريوهات مختلفة بسهولة.
- التحقق من التفاعلات: يمكنك التحقق من أن الكود الذي تقوم باختباره يتفاعل مع الكائنات الوهمية بالطريقة المتوقعة.
مثال بسيط
لنفترض أن لديك فئة UserService
تعتمد على UserRepository
لاسترداد بيانات المستخدم. يمكنك استخدام Mockito لإنشاء كائن وهمي لـ UserRepository
واختبار UserService
دون الحاجة إلى قاعدة بيانات حقيقية.
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
public class UserServiceTest {
@Test
public void testGetUser() {
// إنشاء كائن وهمي لـ UserRepository
UserRepository userRepository = mock(UserRepository.class);
// تعريف السلوك المتوقع للكائن الوهمي
when(userRepository.findUserById(1)).thenReturn(new User(1, "John Doe"));
// إنشاء كائن UserService مع الكائن الوهمي
UserService userService = new UserService(userRepository);
// اختبار طريقة getUser
User user = userService.getUser(1);
// التحقق من النتيجة
assertEquals("John Doe", user.getName());
}
}
في هذا المثال:
- قمنا بإنشاء كائن وهمي لـ
UserRepository
باستخدامmock(UserRepository.class)
. - قمنا بتعريف السلوك المتوقع للكائن الوهمي باستخدام
when(...).thenReturn(...)
. - قمنا باختبار طريقة
getUser
فيUserService
والتحقق من النتيجة باستخدامassertEquals
.
الخلاصة
Mockito هي أداة قوية لاختبار الوحدة في Java، حيث تسمح لك بإنشاء كائنات وهمية والتحكم في سلوكها بسهولة. باستخدام Mockito، يمكنك عزل الكود الذي تريد اختباره والتحقق من تفاعلاته مع التبعيات الأخرى بشكل فعال.
Mockito هي مكتبة قوية لإنشاء الكائنات الوهمية (mocks) لأغراض الاختبار.
- محاكاة التبعيات: استخدم
@Mock
و@InjectMocks
لإنشاء كائنات وهمية. على سبيل المثال:@RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
public void testFindUserById() {
User user = new User();
user.setId(1L);
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(user));
}
ترجمة:
@Test
public void testFindUserById() {
User user = new User();
user.setId(1L);
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(user));
}
ملاحظة: الكود الموجود في الكتلة البرمجية لم يتم ترجمته لأنه يحتوي على أسماء دوال ومتغيرات بالإنجليزية، وهي أمور لا يتم ترجمتها عادةً في البرمجة.
User result = userService.findUserById(1L);
assertNotNull(result);
assertEquals(1L, result.getId().longValue());
}
}
تم ترجمة الكود أعلاه إلى:
User result = userService.findUserById(1L);
assertNotNull(result);
assertEquals(1L, result.getId().longValue());
}
}
ملاحظة: الكود لم يتم ترجمته لأنه يحتوي على أسماء متغيرات ووظائف بالإنجليزية، وهي عادةً لا تُترجم في البرمجة.
- التحقق من السلوك: التحقق من التفاعلات مع الكائنات الوهمية (mock objects). على سبيل المثال:
Mockito.verify(userRepository, times(1)).findById(1L);
الاختبار باستخدام MockMvc
MockMvc يتيح لك اختبار وحدات تحكم Spring MVC.
- الإعداد: قم بتكوين
MockMvc
في فئات الاختبار الخاصة بك. على سبيل المثال:@RunWith(SpringRunner.class) @WebMvcTest(UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc;
@Test
public void testGetUser() throws Exception {
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id").value(1));
}
}
تمت ترجمة الكود أعلاه إلى:
@Test
public void testGetUser() throws Exception {
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id").value(1));
}
}
ملاحظة: الكود لم يتغير لأنه يحتوي على أسماء وظائف ومتغيرات بالإنجليزية، وهي أسماء تقنية لا يتم ترجمتها عادةً.
- بناة الطلبات: استخدم بناة الطلبات لمحاكاة طلبات HTTP. على سبيل المثال:
mockMvc.perform(post("/users") .contentType(MediaType.APPLICATION_JSON) .content("{\"username\":\"john\",\"password\":\"secret\"}")) .andExpect(status().isCreated());
المراقبة والإدارة
Spring Boot Actuator
Spring Boot Actuator هو جزء من إطار عمل Spring Boot الذي يوفر ميزات لمراقبة وإدارة تطبيقاتك. يمكنك استخدامه لجمع مقاييس مختلفة، وفحص صحة التطبيق، وعرض معلومات التكوين، وغير ذلك الكثير. يتم تفعيل هذه الميزات عن طريق إضافة التبعيات المناسبة إلى ملف pom.xml
أو build.gradle
، ثم تكوينها حسب الحاجة.
على سبيل المثال، لإضافة Actuator إلى مشروع Spring Boot باستخدام Maven، يمكنك إضافة التبعية التالية إلى ملف pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
وبعد ذلك، يمكنك الوصول إلى نقاط النهاية المختلفة التي يوفرها Actuator عبر HTTP. على سبيل المثال، يمكنك الوصول إلى معلومات الصحة عن طريق طلب GET إلى /actuator/health
.
curl http://localhost:8080/actuator/health
سيتم إرجاع استجابة JSON تحتوي على حالة صحة التطبيق.
{
"status": "UP"
}
يمكنك أيضًا تكوين نقاط النهاية التي تريد تفعيلها وتعطيلها عبر ملف application.properties
أو application.yml
. على سبيل المثال:
management.endpoints.web.exposure.include=health,info
management.endpoint.health.show-details=always
هذا التكوين سيسمح فقط بنقاط النهاية /actuator/health
و /actuator/info
بالظهور، وسيعرض تفاصيل الصحة دائمًا.
Spring Boot Actuator يوفر مجموعة واسعة من الميزات التي يمكن أن تساعدك في إدارة ومراقبة تطبيقاتك بفعالية.
يوفر Spring Boot Actuator ميزات جاهزة للإنتاج لمراقبة وإدارة تطبيقك.
- النقاط الطرفية (Endpoints): استخدم نقاطًا طرفية مثل
/actuator/health
و/actuator/metrics
لمراقبة صحة التطبيق والمقاييس. على سبيل المثال:curl http://localhost:8080/actuator/health
- نقاط النهاية المخصصة: قم بإنشاء نقاط نهاية مخصصة للـ actuator. على سبيل المثال:
@RestController @RequestMapping("/actuator") public class CustomEndpoint { @GetMapping("/custom") public Map<String, String> customEndpoint() { Map<String, String> response = new HashMap<>(); response.put("status", "نقطة نهاية مخصصة للـ actuator"); return response; } }
مواضيع متقدمة
Spring Advice API
Spring Advice API هي جزء من إطار عمل Spring AOP (Aspect-Oriented Programming) الذي يُستخدم لتطبيق السلوكيات المشتركة عبر تطبيقات Spring. الـ Advice هو الإجراء الذي يتم تنفيذه عند نقطة معينة في تنفيذ البرنامج، مثل قبل أو بعد استدعاء طريقة معينة.
هناك عدة أنواع من الـ Advice في Spring:
- Before Advice: يتم تنفيذه قبل استدعاء طريقة معينة.
- After Returning Advice: يتم تنفيذه بعد استدعاء طريقة معينة بنجاح (بدون استثناءات).
- After Throwing Advice: يتم تنفيذه إذا تم رمي استثناء أثناء استدعاء طريقة معينة.
- After (Finally) Advice: يتم تنفيذه بعد استدعاء طريقة معينة بغض النظر عن النتيجة (سواء تم بنجاح أو مع استثناء).
- Around Advice: يتم تنفيذه حول استدعاء طريقة معينة، مما يسمح بالتحكم في تنفيذ الطريقة بشكل كامل.
مثال على استخدام Before Advice
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("Method is about to be called.");
}
}
في هذا المثال، يتم تنفيذ الـ logBefore
قبل استدعاء أي طريقة في الحزمة com.example.service
.
مثال على استخدام Around Advice
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TimingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("Method execution time: " + (endTime - startTime) + "ms");
return result;
}
}
في هذا المثال، يتم قياس وقت تنفيذ أي طريقة في الحزمة com.example.service
وإخراج الوقت المستغرق.
Spring Advice API يوفر مرونة كبيرة في إدارة السلوكيات المشتركة عبر التطبيق، مما يجعل الكود أكثر نظافة وسهولة في الصيانة.
واجهة برمجة التطبيقات (API) الخاصة بـ Spring تُوفر إمكانيات متقدمة للبرمجة الموجهة نحو الجوانب (AOP).
@Aspect
: قم بتعريف الجوانب باستخدام@Aspect
. على سبيل المثال:@Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("قبل تنفيذ الدالة: " + joinPoint.getSignature().getName()); } }
@After("execution(* com.example.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("بعد تنفيذ الدالة: " + joinPoint.getSignature().getName());
}
- نقاط الالتحاق (Join Points): استخدم نقاط الالتحاق لتحديد الأماكن التي يجب أن تُطبق فيها الجوانب (Aspects). على سبيل المثال:
@Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {}
@Around("serviceMethods()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("قبل تنفيذ الدالة: " + joinPoint.getSignature().getName()); Object result = joinPoint.proceed(); System.out.println("بعد تنفيذ الدالة: " + joinPoint.getSignature().getName()); return result; }
الخلاصة
Spring هو إطار عمل قوي ومتعدد الاستخدامات يمكنه تبسيط تطوير التطبيقات على مستوى المؤسسات. من خلال الاستفادة من ميزات Spring Boot وSpring Data وSpring REST وغيرها من مشاريع Spring، يمكن للمطورين بناء تطبيقات قوية وقابلة للتوسع وسهلة الصيانة بكفاءة. مع إضافة أدوات مثل Spring Boot Actuator وأطر اختبار، يمكنك التأكد من أن تطبيقاتك جاهزة للإنتاج ومختَبرة بشكل جيد.