Skip to content

Commit 6b76fcd

Browse files
committed
refactor(server): Replace InjectorProvider with DependencyInjector for improved dependency injection
1 parent ff9243a commit 6b76fcd

11 files changed

+97
-62
lines changed

src/main/java/com/github/codeboyzhou/mcp/declarative/McpServers.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.github.codeboyzhou.mcp.declarative;
22

3-
import com.github.codeboyzhou.mcp.declarative.common.InjectorModule;
4-
import com.github.codeboyzhou.mcp.declarative.common.InjectorProvider;
53
import com.github.codeboyzhou.mcp.declarative.configuration.McpServerConfiguration;
64
import com.github.codeboyzhou.mcp.declarative.configuration.YAMLConfigurationLoader;
5+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjector;
6+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjectorProvider;
7+
import com.github.codeboyzhou.mcp.declarative.di.GuiceDependencyInjector;
8+
import com.github.codeboyzhou.mcp.declarative.di.GuiceInjectorModule;
79
import com.github.codeboyzhou.mcp.declarative.server.McpServerInfo;
810
import com.github.codeboyzhou.mcp.declarative.server.factory.McpSseServerFactory;
911
import com.github.codeboyzhou.mcp.declarative.server.factory.McpSseServerInfo;
@@ -12,7 +14,6 @@
1214
import com.github.codeboyzhou.mcp.declarative.server.factory.McpStreamableServerInfo;
1315
import com.github.codeboyzhou.mcp.declarative.server.factory.configurable.ConfigurableMcpServerFactories;
1416
import com.google.inject.Guice;
15-
import com.google.inject.Injector;
1617
import io.modelcontextprotocol.util.Assert;
1718
import org.slf4j.Logger;
1819
import org.slf4j.LoggerFactory;
@@ -23,29 +24,29 @@ public class McpServers {
2324

2425
private static final McpServers INSTANCE = new McpServers();
2526

27+
private static DependencyInjector injector;
28+
2629
private McpServers() {
2730
// Using singleton design pattern should have private constructor
2831
}
2932

3033
public static McpServers run(Class<?> applicationMainClass, String[] args) {
31-
InjectorModule module = new InjectorModule(applicationMainClass);
32-
Injector injector = Guice.createInjector(module);
33-
InjectorProvider.initialize(injector);
34+
GuiceInjectorModule module = new GuiceInjectorModule(applicationMainClass);
35+
DependencyInjector injector = new GuiceDependencyInjector(Guice.createInjector(module));
36+
DependencyInjectorProvider.INSTANCE.initialize(injector);
37+
McpServers.injector = injector;
3438
return INSTANCE;
3539
}
3640

3741
public void startStdioServer(McpServerInfo serverInfo) {
38-
Injector injector = InjectorProvider.getInstance().getInjector();
3942
injector.getInstance(McpStdioServerFactory.class).startServer(serverInfo);
4043
}
4144

4245
public void startSseServer(McpSseServerInfo serverInfo) {
43-
Injector injector = InjectorProvider.getInstance().getInjector();
4446
injector.getInstance(McpSseServerFactory.class).startServer(serverInfo);
4547
}
4648

4749
public void startStreamableServer(McpStreamableServerInfo serverInfo) {
48-
Injector injector = InjectorProvider.getInstance().getInjector();
4950
injector.getInstance(McpStreamableServerFactory.class).startServer(serverInfo);
5051
}
5152

src/main/java/com/github/codeboyzhou/mcp/declarative/common/InjectorProvider.java

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.github.codeboyzhou.mcp.declarative.di;
2+
3+
public interface DependencyInjector {
4+
5+
<T> T getInstance(Class<T> type);
6+
7+
<T> T getVariable(Class<T> type, String name);
8+
9+
boolean isInitialized();
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.codeboyzhou.mcp.declarative.di;
2+
3+
public enum DependencyInjectorProvider {
4+
INSTANCE;
5+
6+
private volatile DependencyInjector injector;
7+
8+
public DependencyInjectorProvider initialize(DependencyInjector injector) {
9+
synchronized (this) {
10+
if (this.injector == null) {
11+
this.injector = injector;
12+
}
13+
}
14+
return this;
15+
}
16+
17+
public DependencyInjector getInjector() {
18+
DependencyInjector current = this.injector;
19+
if (current == null) {
20+
throw new IllegalStateException("DependencyInjector has not been initialized yet");
21+
}
22+
return current;
23+
}
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.github.codeboyzhou.mcp.declarative.di;
2+
3+
import com.google.inject.Injector;
4+
import com.google.inject.Key;
5+
import com.google.inject.name.Names;
6+
7+
public class GuiceDependencyInjector implements DependencyInjector {
8+
9+
private final Injector injector;
10+
11+
public GuiceDependencyInjector(Injector injector) {
12+
this.injector = injector;
13+
}
14+
15+
@Override
16+
public <T> T getInstance(Class<T> type) {
17+
if (isInitialized()) {
18+
return injector.getInstance(type);
19+
}
20+
throw new IllegalStateException("GuiceDependencyInjector is not initialized");
21+
}
22+
23+
@Override
24+
public boolean isInitialized() {
25+
return injector != null;
26+
}
27+
28+
@Override
29+
public <T> T getVariable(Class<T> type, String name) {
30+
if (isInitialized()) {
31+
return injector.getInstance(Key.get(type, Names.named(name)));
32+
}
33+
throw new IllegalStateException("GuiceDependencyInjector is not initialized");
34+
}
35+
}

src/main/java/com/github/codeboyzhou/mcp/declarative/common/InjectorModule.java renamed to src/main/java/com/github/codeboyzhou/mcp/declarative/di/GuiceInjectorModule.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.github.codeboyzhou.mcp.declarative.common;
1+
package com.github.codeboyzhou.mcp.declarative.di;
22

33
import static com.google.inject.Scopes.SINGLETON;
44
import static java.util.stream.Collectors.toSet;
@@ -25,13 +25,13 @@
2525
import java.util.Set;
2626
import org.reflections.Reflections;
2727

28-
public final class InjectorModule extends AbstractModule {
28+
public final class GuiceInjectorModule extends AbstractModule {
2929

3030
public static final String INJECTED_VARIABLE_NAME_I18N_ENABLED = "i18nEnabled";
3131

3232
private final Class<?> mainClass;
3333

34-
public InjectorModule(Class<?> mainClass) {
34+
public GuiceInjectorModule(Class<?> mainClass) {
3535
this.mainClass = mainClass;
3636
}
3737

src/main/java/com/github/codeboyzhou/mcp/declarative/server/component/AbstractMcpServerComponentFactory.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package com.github.codeboyzhou.mcp.declarative.server.component;
22

3-
import static com.github.codeboyzhou.mcp.declarative.common.InjectorModule.INJECTED_VARIABLE_NAME_I18N_ENABLED;
3+
import static com.github.codeboyzhou.mcp.declarative.di.GuiceInjectorModule.INJECTED_VARIABLE_NAME_I18N_ENABLED;
44

5-
import com.github.codeboyzhou.mcp.declarative.common.InjectorProvider;
5+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjector;
6+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjectorProvider;
67
import com.github.codeboyzhou.mcp.declarative.util.Strings;
7-
import com.google.inject.Key;
8-
import com.google.inject.name.Names;
98
import java.util.Locale;
109
import java.util.ResourceBundle;
1110
import org.slf4j.Logger;
@@ -20,14 +19,16 @@ public abstract class AbstractMcpServerComponentFactory<T> implements McpServerC
2019

2120
protected static final String NOT_SPECIFIED = "Not Specified";
2221

22+
protected final DependencyInjector injector;
23+
2324
private final ResourceBundle bundle;
2425

2526
private final boolean i18nEnabled;
2627

2728
protected AbstractMcpServerComponentFactory() {
2829
this.bundle = loadResourceBundle();
29-
Key<Boolean> key = Key.get(Boolean.class, Names.named(INJECTED_VARIABLE_NAME_I18N_ENABLED));
30-
this.i18nEnabled = InjectorProvider.getInstance().getInjector().getInstance(key);
30+
this.injector = DependencyInjectorProvider.INSTANCE.getInjector();
31+
this.i18nEnabled = injector.getVariable(Boolean.class, INJECTED_VARIABLE_NAME_I18N_ENABLED);
3132
}
3233

3334
protected String resolveComponentAttributeValue(String attributeLiteralValue) {

src/main/java/com/github/codeboyzhou/mcp/declarative/server/component/McpServerComponentRegister.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import com.github.codeboyzhou.mcp.declarative.annotation.McpResource;
55
import com.github.codeboyzhou.mcp.declarative.annotation.McpTool;
66
import com.github.codeboyzhou.mcp.declarative.common.Immutable;
7-
import com.github.codeboyzhou.mcp.declarative.common.InjectorProvider;
8-
import com.google.inject.Injector;
7+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjector;
8+
import com.github.codeboyzhou.mcp.declarative.di.DependencyInjectorProvider;
99
import io.modelcontextprotocol.server.McpSyncServer;
1010
import java.lang.annotation.Annotation;
1111
import java.lang.reflect.Method;
@@ -15,14 +15,14 @@
1515

1616
public final class McpServerComponentRegister {
1717

18-
private final Injector injector;
18+
private final DependencyInjector injector;
1919

2020
private final Reflections reflections;
2121

2222
private final Immutable<McpSyncServer> server;
2323

2424
public McpServerComponentRegister(McpSyncServer server) {
25-
this.injector = InjectorProvider.getInstance().getInjector();
25+
this.injector = DependencyInjectorProvider.INSTANCE.getInjector();
2626
this.reflections = injector.getInstance(Reflections.class);
2727
this.server = Immutable.of(server);
2828
}

src/main/java/com/github/codeboyzhou/mcp/declarative/server/component/McpServerPromptFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.github.codeboyzhou.mcp.declarative.annotation.McpPrompt;
44
import com.github.codeboyzhou.mcp.declarative.annotation.McpPromptParam;
5-
import com.github.codeboyzhou.mcp.declarative.common.InjectorProvider;
65
import com.github.codeboyzhou.mcp.declarative.util.ObjectMappers;
76
import com.github.codeboyzhou.mcp.declarative.util.Strings;
87
import com.github.codeboyzhou.mcp.declarative.util.Types;
@@ -35,7 +34,7 @@ public McpServerFeatures.SyncPromptSpecification create(Class<?> clazz, Method m
3534
(exchange, request) -> {
3635
Object result;
3736
try {
38-
Object instance = InjectorProvider.getInstance().getInjector().getInstance(clazz);
37+
Object instance = injector.getInstance(clazz);
3938
List<Object> typedValues = asTypedParameterValues(method, request.arguments());
4039
result = method.invoke(instance, typedValues.toArray());
4140
} catch (Exception e) {

src/main/java/com/github/codeboyzhou/mcp/declarative/server/component/McpServerResourceFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.github.codeboyzhou.mcp.declarative.server.component;
22

33
import com.github.codeboyzhou.mcp.declarative.annotation.McpResource;
4-
import com.github.codeboyzhou.mcp.declarative.common.InjectorProvider;
54
import com.github.codeboyzhou.mcp.declarative.util.ObjectMappers;
65
import com.github.codeboyzhou.mcp.declarative.util.Strings;
76
import io.modelcontextprotocol.server.McpServerFeatures;
@@ -37,7 +36,7 @@ public McpServerFeatures.SyncResourceSpecification create(Class<?> clazz, Method
3736
(exchange, request) -> {
3837
Object result;
3938
try {
40-
Object instance = InjectorProvider.getInstance().getInjector().getInstance(clazz);
39+
Object instance = injector.getInstance(clazz);
4140
result = method.invoke(instance);
4241
} catch (Exception e) {
4342
log.error("Error invoking resource method", e);

0 commit comments

Comments
 (0)