Coding Planet
[μ΄νν°λΈ μλ°]chapter2 : [μμ΄ν 3] private μμ±μλ μ΄κ±° νμ μΌλ‘ μ±κΈν΄μμ 보μ¦νλΌ λ³Έλ¬Έ
[μ΄νν°λΈ μλ°]chapter2 : [μμ΄ν 3] private μμ±μλ μ΄κ±° νμ μΌλ‘ μ±κΈν΄μμ 보μ¦νλΌ
jhj.sharon 2023. 8. 9. 23:33
μμ΄ν 3: private μμ±μλ μ΄κ±° νμ μΌλ‘ μ±κΈν΄μμ 보μ¦νλΌ
μ±κΈν΄(sigleton)μ΄λ μΈμ€ν΄μ€λ₯Ό μ€μ§ νλλ§ μμ±ν μ μλ ν΄λμ€λ₯Ό λ§νλ€. μ±κΈν΄μ μ νμ μΈ μλ‘λ ν¨μμ κ°μ 무μν κ°μ²΄λ μ€κ³μ μ μΌν΄μΌνλ μμ€ν μ»΄ν¬λνΈλ₯Ό λ€ μ μλ€. κ·Έλ°λ° ν΄λμ€λ₯Ό μ±κΈν΄μΌλ‘ λ§λ€λ©΄ μ΄λ₯Ό μ¬μ©νλ ν΄λΌμ΄μΈνΈλ₯Ό ν μ€νΈνκΈ°κ° μ΄λ €μμ§ μ μλ€. νμ μ μΈν°νμ΄μ€λ‘ μ μν λ€μ κ·Έ μΈν°νμ΄μ€λ₯Ό ꡬνν΄μ λ§λ μ±κΈν΄μ΄ μλλΌλ©΄ μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό κ°μ§(mock)ꡬνμΌλ‘ λ체ν μ μκΈ° λλ¬Έμ΄λ€. μ¦, ν΄λμ€λ₯Ό μ±κΈν΄μΌλ‘ λ§λ€ κ²½μ° ν΄λΉ ν΄λμ€μ μΈμ€ν΄μ€κ° μμ€ν μ 체μ νλμ΄κΈ° λλ¬Έμ ν μ€νΈμ μ€μ νκ²½μμμ λμμ΄ κ°νκ² κ²°ν©λ μ μλ€.
μ±κΈν΄μ λ§λλ λ°©λ²μ λ³΄ν΅ λκ°μ§μ΄λ€. λ λ°©μ λͺ¨λ μμ±μλ privateμΌλ‘ κ°μΆ°λκ³ μ μΌν μΈμ€ν΄μ€μ μ κ·Όν μ μλ μλ¨μΌλ‘ public static λ©€λ²λ₯Ό νλ λ§λ€μ΄ λλ€.
1. public static final νλ λ°©μμ μ±κΈν΄
1) νΉμ§ λ° νμ
(1) Private μμ±μ
- μμ±μλ₯Ό 'private'μΌλ‘ μ μΈνμ¬ μΈλΆμμ μ΄ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±ν μ μκ² νλ€.
- publicμ΄λ protectedμμ±μκ° μμΌλ―λ‘ μμ±μκ° μ΄κΈ°νλ λ λ§λ€μ΄μ§ μΈμ€ν΄μ€κ° μ 체 μμ€ν μμ νλλΏμμ΄ λ³΄μ₯λλ€.
- μμΈμ μΌλ‘ κΆνμ΄ μλ ν΄λΌμ΄μΈνΈλ 리νλ μ APIμΈ AccesibleObject.setAccessibleμ μ¬μ©ν΄ priavate μμ±μλ₯Ό νΈμΆ ν μ μλ€. μ΄λ¬ν 곡격μ λ°©μ΄νλ €λ©΄ μμ±μλ₯Ό μμ νμ¬ λ λ² μ§Έ κ°μ²΄κ° μμ±λλ €ν λ μμΈλ₯Ό λμ§κ²νλ©΄ λλ€.
AccessibleObject.setAccessibleλ Javaμ 리νλ μ
APIμ μνλ λ©μλμ΄λ€.리νλ μ
APIλ νλ‘κ·Έλ¨ μ€ν μ€μ (λ°νμμμ) Java ν΄λμ€μ λ΄λΆ ꡬ쑰λ₯Ό κ²μ¬νκ±°λ μμ ν μ μκ² ν΄μ£Όλ κ°λ ₯ν κΈ°λ₯λ€μ μ 곡νλ€. AccessibleObject.setAccessible λ©μλλ Field, Method, κ·Έλ¦¬κ³ Constructorμ κ°μ 리νλ μ κ°μ²΄μ μ κ·Ό μ μ΄λ₯Ό μ°νν μ μλ€. |
(2) Public static final νλ
- 'public static final'λ‘ μ μΈλ 'INSTANCE' νλλ ν΄λμ€ λ‘λ μ ν λ²λ§ μ΄κΈ°ν λλ€. μ΄ νλλ μ΄ ν΄λμ€μ μ μΌν μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°νλ€.
(3) Static μ΄κΈ°ν
- 'INSTANCE'λ μ μ μ΄κΈ°ν λΈλ‘μμ μ΄κΈ°νλλ€(μ μ μ΄κΈ°ν λΈλ‘(static intitialization block_μ ν΄λμ€κ° JVMμ μν΄ μ²μ λ‘λλ λ ν λ²λ§ μ€νλλ€.).
- Javaλ μ μ μ΄κΈ°νκ° μ€λ λ μμ (Thread-safety)νκ² μνλλλ‘ λ³΄μ₯ νλ―λ‘ λ©ν°μ€λ λ νκ²½μμλ μμ νλ€. μ¦, μ±κΈν΄ ν¨ν΄μμλ ν΄λμ€ λ‘λ© λ° μ΄κΈ°ν κ³Όμ μ λκΈ°ν νλ JVMμ λμ λ°©μμ νμ©νκΈ° λλ¬Έμ μΈμ€ν΄μ€μ μ€λ λ μμ ν μ΄κΈ°νλ₯Ό 보μ₯νλ€.
import java.lang.reflect.Constructor;
public class Singleton {
// μκΈ° μμ μ μΈμ€ν΄μ€λ₯Ό static final νλλ‘ μμ±
public static final Singleton INSTANCE = new Singleton();
private static boolean isInstanceCreated = false;
// private μμ±μλ‘ μΈλΆμμ μΈμ€ν΄μ€ μμ±μ λ°©μ§
private Singleton() {
if (isInstanceCreated) {
throw new IllegalStateException("Instance already created!");
}
isInstanceCreated = true;
}
// νμν λΉμ¦λμ€ λ©μλ
public void someMethod() {
// ...
}
public class ReflectionAttack {
public static void main(String[] args) throws Exception {
// μ μμ μΈ λ°©λ²μΌλ‘ μ±κΈν΄ μΈμ€ν΄μ€ νλ
Singleton instance1 = Singleton.INSTANCE;
// 리νλ μ
μ μ¬μ©ν 곡격
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true); // private μμ±μμ μ κ·Ό μ μ΄ μ°ν
Singleton instance2 = constructor.newInstance();
System.out.println(instance1 == instance2); // false
}
}
//μ¬μ©λ°©λ²
Singleton singleton = Singleton.INSTANCE;
singleton.someMethod();
2) μ₯μ
- ν΄λΉ ν΄λμ€κ° μ±κΈν΄μμ΄ APIμ λͺ ννκ² λλ¬λλ€. public static νλκ° finalμ΄λ―λ‘ μ λλ‘ λ€λ₯Έ κ°μ²΄λ₯Ό μ°Έμ‘°ν μ μλ€.
- ꡬνμ΄ κ°λ¨νλ€.
- JVMμ ν΄λμ€ λ‘λ© λ©μ»€λμ¦μ νμ©νμ¬ μ€λ λ μμ μ±μ 보μ₯νλ€.
3) λ¨μ
- μ±κΈν΄ μΈμ€ν΄μ€κ° μ¬μ©λμ§ μλλΌλ ν΄λμ€κ° λ‘λλ λ μμ±λλ€. (μ¦μ λ‘λ©, Eager Loading)
- μΈμ€ν΄μ€ μμ± λ‘μ§μ λ³κ²½νκ±°λ, μ΄κΈ°νμ μΆκ° μμ μ΄ νμν κ²½μ° κ΅¬νμ΄ λ³΅μ‘ν΄μ§ μ μλ€.
2. μ μ ν©ν°λ¦¬ λ°©μμ μ±κΈν΄
1) νΉμ§ λ° νμ
(1) Private μμ±μ & (2) Public static final νλ λμΌ
(3) Public static λ©μλ
- μΈλΆμμ μ΄ λ©μλλ₯Ό ν΅ν΄ μ±κΈν΄ μΈμ€ν΄μ€μ μ κ·Όν μ μλ€. μ²μ νΈμΆλ λ μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννκ±°λ μ΄λ―Έ μ΄κΈ°νλ μΈμ€ν΄μ€λ₯Ό λ°ννλ€.
public class Singleton {
// Private static instance
private static final Singleton INSTANCE = new Singleton();
// Private constructor
private Singleton() {
// Initialization logic
}
// Public static factory method
public static Singleton getInstance() {
return INSTANCE;
}
// μ΄ λ©μλλ₯Ό μΆκ°νμ¬ μμ§λ ¬ν μ μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό λ°ν.
private Object readResolve() {
return INSTANCE;
}
}
//μ¬μ©λ°©λ²
Singleton singleton = Singleton.getInstance();
2) μ₯μ
- μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό λ°ννλ λ©μλμ μ΄λ¦μ μμ λ‘κ² μ§μ ν μ μλ€.
- λμ€μ μ±κΈν΄μ΄ μλκ² λ³κ²½νλλΌλ APIλ₯Ό λ³κ²½νμ§ μκ³ κ΅¬νλ§ λ³κ²½ν μ μλ€. μ μΌν μΈμ€ν΄μ€λ₯Ό λ°ννλ ν©ν°λ¦¬ λ©μλκ° νΈμΆνλ μ€λ λλ³λ‘ λ€λ₯Έ μΈμ€ν΄μ€λ₯Ό λκ²¨μ£Όκ² ν μ μλ€.
- μ μ ν©ν°λ¦¬ λ°©μμ μ¬μ©νλ©΄, μ λλ¦ μ±κΈν΄μ λ§λ€ μ μλ€.
- μ μ ν©ν°λ¦¬μ λ©μλ μ°Έμ‘°λ₯Ό 곡κΈμ(supplier)λ‘ μ¬μ©ν μ μλ€. μ΄λ¬ν λ°©μμΌλ‘, λ©μλ μ°Έμ‘°μ 곡κΈμλ₯Ό ν¨κ» μ¬μ©νλ©΄ κΈ°μ‘΄ λ©μλμ λ‘μ§μ μ¬μ¬μ©νλ©΄μ ν¨μν νλ‘κ·Έλλ° μ€νμΌμ μ μ©ν μ μλ€.
- λ©μλ μ°Έμ‘°(Method Reference) : λλ€ ννμμ λ λ€λ₯Έ κ°λ¨ν νν. κΈ°μ‘΄ λ©μλμ λμμ μ¬μ¬μ©νκ±°λ νΉμ λ©μλλ₯Ό ν¨μν μΈν°νμ΄μ€μ ꡬνμΌλ‘ μ°Έμ‘°νκ³ μΆμ λ μ¬μ©νλ€. λ©μλ μ°Έμ‘°λ '::' μ°μ°μλ₯Ό μ¬μ©νμ¬ νννλ€. - 곡κΈμ(Supplier) : 곡κΈμλ 맀κ°λ³μλ₯Ό λ°μ§ μκ³ κ°μ λ°ννλ 'get()' λ©μλλ₯Ό μ 곡νλ€. |
Supplier<Singleton> singletonSupplier = Singleton::getInstance;
// μ΄μ supplierλ₯Ό μ¬μ©νμ¬ Singleton μΈμ€ν΄μ€λ₯Ό μ»μ μ μλ€.
Singleton singleton = singletonSupplier.get();
** μ±κΈν΄μ μ§λ ¬ν(Serializable)
(μ§λ ¬νμ λν ν¬μ€νΈ μ°Έμ‘° : https://sharonprogress.tistory.com/manage/posts/)
- μ±κΈν΄ ν΄λμ€κ° 'Serializable'μΈν°νμ΄μ€λ₯Ό ꡬννλ©΄, κ°μ²΄μ μ§λ ¬ν λ° μμ§λ ¬νλ₯Ό ν΅ν΄ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±ν μ μλ€. μ΄λ‘μΈν΄ μ±κΈν΄μ κΈ°λ³ΈμμΉμ΄ κΉ¨μ§κ² λλ€.
- μμμ μκ°ν λ μ€ νλμ λ°©μμΌλ‘ λ§λ μ±κΈν΄ ν΄λμ€λ₯Ό μ§λ ¬ννλ €λ©΄ λ¨μν Serializableμ μ μΈνλ κ²λ§μΌλ‘λ λΆμ‘±νλ€. λͺ¨λ μΈμ€ν΄μ€ νλλ₯Ό μΌμμ (transient)μ΄λΌκ³ μ μΈν΄μΌνκ³ readResolve λ©μλλ₯Ό μ 곡ν΄μΌνλ€.
- readResolve()λ©μλλ μμ§λ ¬ν μ μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό λ°ννλλ‘ λ³΄μ₯ν μ μλ€. μ€μ λ‘ readResolve()λ μμ§λ ¬ν μ€μ νΈμΆλμ΄ λ체ν κ°μ²΄λ₯Ό λ°ννλ€.
3. μ΄κ±° νμ λ°©μμ μ±κΈν΄ - λ°λμ§ν λ°©λ²
1) νΉμ§ λ° νμ
- μ΄κ±° νμ λ°©μμ μ±κΈν΄μ μ±κΈν΄μ ꡬννλ κ°μ₯ λ°λμ§ν λ°©λ² μ€μ νλμ΄λ€. public νλ λ°©λ²κ³Ό λΉμ·νμ§λ§ λ κ°κ²°νκ³ μΆκ° λ Έλ ₯μμ΄ μ§λ ¬ν ν μ μλ€. enumμ μ μλ κ° μμλ ν΄λΉ enum νμ μ μΈμ€ν΄μ€λ₯Ό λνλΈλ€.
- enumμμ μμ±μλ₯Ό μ μνλ κ²μ κ°λ₯νλ€. κ·Έλ¬λ, enumμ μμ±μλ νμ private μ΄λ―λ‘γ μΈλΆμμ enumμ μμ±μλ₯Ό νΈμΆνμ¬ μ μΈμ€ν΄μ€λ₯Ό λ§λλ κ²μ λΆκ°λ₯νλ€.
public enum Singleton {
INSTANCE;
public void someMethod() {
// μ±κΈν΄ κ°μ²΄μ λμμ μ μ
}
}
//μ¬μ© λ°©λ²
Singleton singleton = Singleton.INSTANCE;
singleton.someMethod();
2) μ₯μ
- κ°κ²°μ±: μ½λκ° λ§€μ° κ°κ²°νλ©°, λͺ μμ μΌλ‘ μ±κΈν΄μμ λνλΈλ€.
- μ§λ ¬νμ μμ : μ΄κ±° νμ μ μ§λ ¬νμ μμ§λ ¬νκ° JVMμ μν΄ κ΄λ¦¬λλ―λ‘, μλ‘μ΄ κ°μ²΄κ° μμ±λλ λ¬Έμ κ° λ°μνμ§ μλλ€.
- 리νλ μ μ μμ : Javaμ enum μμ±μλ νμ privateμ΄λ€. μ΄κ²μ μΈμ΄ μ체μ μν΄ κ°μ λλ―λ‘, 리νλ μ μ μ¬μ©νμ¬ μμ±μμ μ κ·Ό μ νμ λ³κ²½ν μ μλ€. λν enum νμ μ μμμ μλ§νΌλ§ μΈμ€ν΄μ€λ₯Ό κ°μ§ μ μκ³ μ΄λ JVMμμ κ΄λ¦¬λκΈ° λλ¬Έμ 리νλ μ μ μ¬μ©νμ¬ μΆκ° μΈμ€ν΄μ€λ₯Ό λ§λλ κ²μ λΆκ°λ₯νλ€.
- λ©ν°μ€λ λ©μ μμ : μ΄κ±° νμ μ μμ±μ μλ°μμ μ€λ λ μμ νκ² μνλλ€.
3) λ¨μ
- λ§λ€λ €λ μ±κΈν΄μ΄ Enum μΈμ ν΄λμ€λ₯Ό μμν΄μΌ νλ€λ©΄ μ΄ λ°©λ²μ μ¬μ©ν μ μλ€.
- μ΄κ±° νμ μ΄ λ€λ₯Έ μΈν°νμ΄μ€λ₯Ό ꡬννλλ‘ μ μΈν μ λ μλ€.