Skip to content

Commit 9367adb

Browse files
committed
Stage 1 - Lesson 28
1 parent fe8c5ec commit 9367adb

23 files changed

+939
-86
lines changed

projects/stage-1/middleware-frameworks/my-cdi/src/main/java/org/geektimes/enterprise/inject/standard/AnnotatedTypeInjectionTarget.java

+12-45
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,19 @@ public T produce(CreationalContext<T> ctx) {
7272

7373
@Override
7474
public void dispose(T instance) {
75-
Class<?> beanClass = instance.getClass();
76-
Set<Type> beanTypes = getBeanTypes(beanClass);
75+
// DO NOTHING
7776
}
7877

78+
/**
79+
* {@inheritDoc}
80+
* <p>
81+
* When the Bean implementation performs dependency injection, it must obtain the contextual instances to inject
82+
* by calling BeanManager.getInjectableReference(), passing an instance of InjectionPoint that represents the
83+
* injection point and the instance of CreationalContext that was passed to Bean.create().
84+
*
85+
* @param instance
86+
* @param ctx
87+
*/
7988
@Override
8089
public void inject(T instance, CreationalContext<T> ctx) {
8190
// Injected Fields
@@ -156,24 +165,6 @@ public AnnotatedType<T> getAnnotatedType() {
156165
return annotatedType;
157166
}
158167

159-
public Map<AnnotatedConstructor, List<ConstructorParameterInjectionPoint>> getConstructorParameterInjectionPointsMap() {
160-
if (constructorParameterInjectionPointsMap == null) {
161-
constructorParameterInjectionPointsMap = Injections.getConstructorParameterInjectionPointsMap(getAnnotatedType(), bean);
162-
}
163-
return constructorParameterInjectionPointsMap;
164-
}
165-
166-
public List<ConstructorParameterInjectionPoint> getConstructorParameterInjectionPoints() {
167-
Map<AnnotatedConstructor, List<ConstructorParameterInjectionPoint>> injectionPointsMap =
168-
getConstructorParameterInjectionPointsMap();
169-
if (injectionPointsMap.isEmpty()) {
170-
return emptyList();
171-
}
172-
List<ConstructorParameterInjectionPoint> injectionPoints = new LinkedList<>();
173-
injectionPointsMap.values().forEach(injectionPoints::addAll);
174-
return unmodifiableList(injectionPoints);
175-
}
176-
177168
public Set<FieldInjectionPoint> getFieldInjectionPoints() {
178169
if (fieldInjectionPoints == null) {
179170
fieldInjectionPoints = Injections.getFieldInjectionPoints(getAnnotatedType(), bean);
@@ -188,32 +179,8 @@ public Map<AnnotatedMethod, Set<MethodParameterInjectionPoint>> getMethodParamet
188179
return methodParameterInjectionPointsMap;
189180
}
190181

191-
public List<MethodParameterInjectionPoint> getMethodParameterInjectionPoints() {
192-
List<MethodParameterInjectionPoint> injectionPoints = new LinkedList<>();
193-
getMethodParameterInjectionPointsMap().values().forEach(injectionPoints::addAll);
194-
return unmodifiableList(injectionPoints);
195-
}
196-
197182
@Override
198183
public Set<InjectionPoint> getInjectionPoints() {
199-
200-
List<ConstructorParameterInjectionPoint> constructorParameterInjectionPoints = getConstructorParameterInjectionPoints();
201-
202-
Set<FieldInjectionPoint> fieldInjectionPoints = getFieldInjectionPoints();
203-
204-
List<MethodParameterInjectionPoint> methodParameterInjectionPoints = getMethodParameterInjectionPoints();
205-
206-
int size = constructorParameterInjectionPoints.size() + fieldInjectionPoints.size()
207-
+ methodParameterInjectionPoints.size();
208-
209-
Set<InjectionPoint> injectionPoints = newLinkedHashSet(size);
210-
// add the InjectionPoints from Constructors' parameters
211-
injectionPoints.addAll(constructorParameterInjectionPoints);
212-
// add the InjectionPoints from Fields
213-
injectionPoints.addAll(fieldInjectionPoints);
214-
// add the InjectionPoints from Methods' parameters
215-
injectionPoints.addAll(methodParameterInjectionPoints);
216-
217-
return unmodifiableSet(injectionPoints);
184+
return bean.getInjectionPoints();
218185
}
219186
}

projects/stage-1/middleware-frameworks/my-cdi/src/main/java/org/geektimes/enterprise/inject/standard/beans/GenericBean.java

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
/**
3737
* Generic implementation for {@link Bean Bean}, which extends {@link GenericBeanAttributes}
38+
* <p>
39+
* Implementations of {@link Bean Bean} usually maintain a reference to an instance of {@link BeanManager}.
3840
*
3941
* @param <T> the class of the bean instance
4042
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>

projects/stage-1/middleware-frameworks/my-cdi/src/main/java/org/geektimes/enterprise/inject/standard/beans/manager/StandardBeanManager.java

+90-35
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import java.util.*;
6363
import java.util.function.Function;
6464

65+
import static java.lang.String.format;
6566
import static java.lang.System.getProperty;
6667
import static java.util.Collections.unmodifiableList;
6768
import static java.util.Objects.requireNonNull;
@@ -141,6 +142,10 @@ public class StandardBeanManager implements BeanManager, Instance<Object> {
141142
private final Set<DeploymentException> deploymentProblems;
142143

143144

145+
private boolean firedAfterBeanDiscoveryEvent = false;
146+
147+
private boolean firedAfterDeploymentValidationEvent = false;
148+
144149
public StandardBeanManager() {
145150
this.classLoader = ClassLoaderUtils.getClassLoader(getClass());
146151

@@ -170,13 +175,20 @@ public StandardBeanManager() {
170175

171176
@Override
172177
public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx) {
178+
assertAfterDeploymentValidation();
179+
if (!Objects.equals(beanType.getTypeName(), bean.getBeanClass().getTypeName())) {
180+
throw new IllegalArgumentException(format("The given type[%s] is not a bean type[%s] of the given bean!",
181+
beanType.getTypeName(),
182+
bean.getBeanClass()));
183+
}
173184
Class<? extends Annotation> scope = bean.getScope();
174-
// TODO
175-
return null;
185+
Context context = getContext(scope);
186+
return context.get((Contextual) bean, ctx);
176187
}
177188

178189
@Override
179190
public Object getInjectableReference(InjectionPoint ij, CreationalContext<?> ctx) {
191+
assertAfterDeploymentValidation();
180192
// TODO
181193
return null;
182194
}
@@ -189,30 +201,35 @@ public <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual
189201

190202
@Override
191203
public Set<Bean<?>> getBeans(Type beanType, Annotation... qualifiers) {
204+
assertAfterBeanDiscovery();
192205
// TODO
193206
return null;
194207
}
195208

196209
@Override
197210
public Set<Bean<?>> getBeans(String name) {
211+
assertAfterBeanDiscovery();
198212
// TODO
199213
return null;
200214
}
201215

202216
@Override
203217
public Bean<?> getPassivationCapableBean(String id) {
218+
assertAfterBeanDiscovery();
204219
// TODO
205220
return null;
206221
}
207222

208223
@Override
209224
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans) {
225+
assertAfterBeanDiscovery();
210226
// TODO
211227
return null;
212228
}
213229

214230
@Override
215231
public void validate(InjectionPoint injectionPoint) {
232+
assertAfterBeanDiscovery();
216233
Annotated annotated = injectionPoint.getAnnotated();
217234
if (annotated instanceof AnnotatedField) { // InjectionPoint on Field
218235
validateFieldInjectionPoint(injectionPoint);
@@ -226,6 +243,39 @@ public void validate(InjectionPoint injectionPoint) {
226243
}
227244
}
228245

246+
/**
247+
* @param injectionPoint {@link InjectionPoint}
248+
* @throws DefinitionException If an injected field is annotated @Produces, the container automatically detects
249+
* the problem and treats it as a definition error.
250+
*/
251+
private void validateFieldInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
252+
validateForbiddenAnnotation(injectionPoint, Produces.class);
253+
}
254+
255+
/**
256+
* @param injectionPoint {@link InjectionPoint}
257+
* @throws DefinitionException If a bean constructor has a parameter annotated @Disposes, @Observes, or @ObservesAsync,
258+
* the container automatically detects the problem and treats it as a definition error.
259+
*/
260+
private void validateConstructorParameterInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
261+
validateForbiddenAnnotation(injectionPoint, Disposes.class);
262+
validateForbiddenAnnotation(injectionPoint, Observes.class);
263+
validateForbiddenAnnotation(injectionPoint, ObservesAsync.class);
264+
}
265+
266+
/**
267+
* @param injectionPoint {@link InjectionPoint}
268+
* @throws DefinitionException If an initializer method is annotated @Produces, has a parameter annotated @Disposes,
269+
* has a parameter annotated @Observes, or has a parameter annotated @ObservesAsync,
270+
* the container automatically detects the problem and treats it as a definition error.
271+
*/
272+
private void validateMethodParameterInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
273+
validateForbiddenAnnotation((Method) injectionPoint.getMember(), Produces.class);
274+
validateForbiddenAnnotation(injectionPoint, Disposes.class);
275+
validateForbiddenAnnotation(injectionPoint, Observes.class);
276+
validateForbiddenAnnotation(injectionPoint, ObservesAsync.class);
277+
}
278+
229279
/**
230280
* Is defining annotation type or not.
231281
* <p>
@@ -272,39 +322,6 @@ public boolean isDefiningAnnotationType(Class<?> type, boolean includedIntercept
272322
return hasDefiningAnnotation;
273323
}
274324

275-
/**
276-
* @param injectionPoint {@link InjectionPoint}
277-
* @throws DefinitionException If an injected field is annotated @Produces, the container automatically detects
278-
* the problem and treats it as a definition error.
279-
*/
280-
private void validateFieldInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
281-
validateForbiddenAnnotation(injectionPoint, Produces.class);
282-
}
283-
284-
/**
285-
* @param injectionPoint {@link InjectionPoint}
286-
* @throws DefinitionException If a bean constructor has a parameter annotated @Disposes, @Observes, or @ObservesAsync,
287-
* the container automatically detects the problem and treats it as a definition error.
288-
*/
289-
private void validateConstructorParameterInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
290-
validateForbiddenAnnotation(injectionPoint, Disposes.class);
291-
validateForbiddenAnnotation(injectionPoint, Observes.class);
292-
validateForbiddenAnnotation(injectionPoint, ObservesAsync.class);
293-
}
294-
295-
/**
296-
* @param injectionPoint {@link InjectionPoint}
297-
* @throws DefinitionException If an initializer method is annotated @Produces, has a parameter annotated @Disposes,
298-
* has a parameter annotated @Observes, or has a parameter annotated @ObservesAsync,
299-
* the container automatically detects the problem and treats it as a definition error.
300-
*/
301-
private void validateMethodParameterInjectionPoint(InjectionPoint injectionPoint) throws DefinitionException {
302-
validateForbiddenAnnotation((Method) injectionPoint.getMember(), Produces.class);
303-
validateForbiddenAnnotation(injectionPoint, Disposes.class);
304-
validateForbiddenAnnotation(injectionPoint, Observes.class);
305-
validateForbiddenAnnotation(injectionPoint, ObservesAsync.class);
306-
}
307-
308325
@Override
309326
@Deprecated
310327
public void fireEvent(Object event, Annotation... qualifiers) {
@@ -315,17 +332,20 @@ public void fireEvent(Object event, Annotation... qualifiers) {
315332

316333
@Override
317334
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers) {
335+
assertAfterBeanDiscovery();
318336
return (Set) observerMethodsManager.resolveObserverMethods(event, qualifiers);
319337
}
320338

321339
@Override
322340
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {
341+
assertAfterBeanDiscovery();
323342
// TODO
324343
return null;
325344
}
326345

327346
@Override
328347
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
348+
assertAfterBeanDiscovery();
329349
// TODO
330350
return null;
331351
}
@@ -415,6 +435,7 @@ public <T> AnnotatedType<T> createAnnotatedType(Class<T> type) {
415435
@Deprecated
416436
@Override
417437
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type) {
438+
418439
return null;
419440
}
420441

@@ -491,6 +512,7 @@ public Event<Object> getEvent() {
491512

492513
@Override
493514
public Instance<Object> createInstance() {
515+
assertAfterBeanDiscovery();
494516
// TODO
495517
return null;
496518
}
@@ -825,11 +847,29 @@ private void registerDecoratorBeans() {
825847
/**
826848
* the container must fire an event of type AfterBeanDiscovery, as defined in AfterBeanDiscovery event, and abort
827849
* initialization of the application if any observer registers a definition error.
850+
* An exception is thrown if the following operations are called before the AfterBeanDiscovery event is fired:
851+
* <ul>
852+
* <li>{@link #getBeans(String)}</li>
853+
* <li>{@link #getBeans(Type, Annotation...)}</li>
854+
* <li>{@link #getPassivationCapableBean(String)}</li>
855+
* <li>{@link #resolve(Set)}</li>
856+
* <li>{@link #resolveDecorators(Set, Annotation...)}</li>
857+
* <li>{@link #resolveInterceptors(InterceptionType, Annotation...)}</li>
858+
* <li>{@link #resolveObserverMethods(Object, Annotation...)}</li>
859+
* <li>{@link #validate(InjectionPoint)}</li>
860+
* </ul>
828861
*/
829862
private void performAfterBeanDiscovery() {
830863
fireAfterBeanDiscoveryEvent();
831864
}
832865

866+
private void assertAfterBeanDiscovery() {
867+
if (!firedAfterBeanDiscoveryEvent) {
868+
throw new UnsupportedOperationException("Current operation must not be invoked before " +
869+
"AfterBeanDiscovery event is fired!");
870+
}
871+
}
872+
833873
/**
834874
* the container must detect deployment problems by validating bean dependencies and specialization and abort
835875
* initialization of the application if any deployment problems exist, as defined in Problems detected automatically
@@ -842,11 +882,24 @@ private void performDeploymentValidation() {
842882
/**
843883
* the container must fire an event of type AfterDeploymentValidation, as defined in AfterDeploymentValidation event,
844884
* and abort initialization of the application if any observer registers a deployment problem.
885+
* An exception is thrown if the following operations are called before the AfterBeanDiscovery event is fired:
886+
* <ul>
887+
* <li>{@link #createInstance()}</li>
888+
* <li>{@link #getReference(Bean, Type, CreationalContext)}</li>
889+
* <li>{@link #getInjectableReference(InjectionPoint, CreationalContext)}</li>
890+
* </ul>
845891
*/
846892
private void performAfterDeploymentValidation() {
847893
fireAfterDeploymentValidationEvent();
848894
}
849895

896+
private void assertAfterDeploymentValidation() {
897+
if (!firedAfterDeploymentValidationEvent) {
898+
throw new UnsupportedOperationException("Current operation must not be invoked before " +
899+
"AfterDeploymentValidation event is fired");
900+
}
901+
}
902+
850903
private StandardBeanManager discoverExtensions() {
851904
load(Extension.class, classLoader).forEach(this::addExtension);
852905
return this;
@@ -930,6 +983,7 @@ private void fireProcessProducerEvent(AnnotatedMember annotatedMember, Producer
930983
*/
931984
private void fireAfterBeanDiscoveryEvent() {
932985
fireEvent(new AfterBeanDiscoveryEvent(this));
986+
firedAfterBeanDiscoveryEvent = true;
933987
}
934988

935989

@@ -939,6 +993,7 @@ private void fireAfterBeanDiscoveryEvent() {
939993
*/
940994
private void fireAfterDeploymentValidationEvent() {
941995
fireEvent(new AfterDeploymentValidationEvent(this));
996+
firedAfterDeploymentValidationEvent = true;
942997
}
943998

944999
private void fireEvent(Object event) {

projects/stage-1/middleware-frameworks/my-cdi/src/main/java/org/geektimes/enterprise/inject/standard/context/ApplicationScopedContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
2929
* @since 1.0.0
3030
*/
31-
public class ApplicationScopedContext extends AbstractContext {
31+
public class ApplicationScopedContext extends AbstractAlterableContext {
3232

3333
public ApplicationScopedContext(BeanManager beanManager) {
3434
super(beanManager, ApplicationScoped.class);

0 commit comments

Comments
 (0)