ConstructorBasedInstantiationStrategy.java

package sprout.beans.instantiation;

import net.sf.cglib.proxy.Enhancer;
import sprout.beans.BeanCreationMethod;
import sprout.beans.BeanDefinition;
import sprout.beans.ConstructorBeanDefinition;
import sprout.context.BeanFactory;
import sprout.context.ConfigurationMethodInterceptor;

import java.lang.reflect.Constructor;

/**
 * 생성자 기반 빈 인스턴스화 전략
 */
public class ConstructorBasedInstantiationStrategy implements BeanInstantiationStrategy {

    @Override
    public Object instantiate(BeanDefinition def, DependencyResolver dependencyResolver, BeanFactory beanFactory) throws Exception {
        Constructor<?> constructor = def.getConstructor();
        Object[] deps;

        // ConstructorBeanDefinition인 경우 미리 준비된 생성자 인자 사용
        if (def instanceof ConstructorBeanDefinition && ((ConstructorBeanDefinition) def).getConstructorArguments() != null) {
            deps = ((ConstructorBeanDefinition) def).getConstructorArguments();
        } else {
            // 의존성 해결
            deps = dependencyResolver.resolve(
                    def.getConstructorArgumentTypes(),
                    constructor.getParameters(),
                    def
            );
        }

        // Configuration 클래스의 경우 CGLIB 프록시 생성
        if (def.isConfigurationClassProxyNeeded()) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(def.getType());
            enhancer.setCallback(new ConfigurationMethodInterceptor(beanFactory));
            return enhancer.create(def.getConstructorArgumentTypes(), deps);
        } else {
            // 접근 권한 설정 (private/package-private 생성자 접근 가능하게)
            constructor.setAccessible(true);
            return constructor.newInstance(deps);
        }
    }

    @Override
    public boolean supports(BeanCreationMethod method) {
        return method == BeanCreationMethod.CONSTRUCTOR;
    }
}