- Objective - to register a
Classroom
bean which mediates a compositeStudents
andInstructors
bean reference. - Purpose - to demonstrate the use of
- Bean registration
- Dependency Injection
- IOC Container
AnnotationConfigApplicationContext
- Annotations
@Bean
@DependsOn
@Autowired
@PostConstruct
@Config
@SpringBootTest
@Qualifier
- Do NOT clone this repository until completing
Part 0.0
- You may structure this project and the packaging how you please, however keep in mind that
@Configuration
scans from current directory down. - Until
Part 10
, this project is nearly identical to theLearnerLab
completed in the past.
- Navigate to start.spring.io
- In the
Search for Dependencies
input box search forDevTools
Web
- Select
Generate Project
- After the project has completed downloading, navigate to the download directory and unzip the project folder.
- At the root directory of the project, clone this repository.
- Move all files from the
demo
project generated bystart.spring.io
, into the newly clonedlearnerlab
folder. - Open the project via its
pom.xml
from IntelliJ > File > Open- Be sure to
Open as Project
when prompted
- Be sure to
- Create a
Person
class.- The class should declare a
final
field namedid
of typelong
. - The class should declare a field named
name
of typeString
. Person
constructor should have a parameter of typeLong id, String name
which sets each of the fields to their respective value.- The class should define a
getId()
method which returns thePerson
object'sid
field. - The class should define a
getName()
method which returns thePerson
object'sname
field. - The class should define a
setName()
method which sets thePerson
object'sname
field.
- The class should declare a
- Create a
Learner
interface.Learner
should declare one method signature:- Method name:
learn
- Method parameters:
double numberOfHours
- Method return-type:
void
- Method name:
- Create a
Student
class such that:Student
is a subclass ofPerson
Student
implements theLearner
interfaceStudent
should have an instance variabletotalStudyTime
of typedouble
Student
should have a concrete implementation of thelearn
method which increments thetotalStudyTime
variable by the specifiednumberOfHours
argument.Student
should have agetTotalStudyTime()
method which returns thetotalStudyTime
instance variable.
- Create a
Teacher
interface.-
Teacher
should declare ateach
method signature:- Method name:
teach
- Method parameters:
Learner learner
double numberOfHours
- Method return-type:
void
- Method name:
-
Teacher
should declare alecture
method signature:- Method name:
lecture
- Method parameters:
Iterable<? extends Learner> learners
double numberOfHours
- Method return-type:
void
- Method name:
-
- Create an
Instructor
class such that:Instructor
is a subclass ofPerson
Instructor
implements theTeacher
interfaceInstructor
should have a concrete implementation of theteach
method which invokes thelearn
method on the specifiedLearner
object.Instructor
should have a concrete implementation of thelecture
method which invokes thelearn
method on each of the elements in the specified array ofLearner
objects.numberOfHours
should be evenly split amongst the learners.double numberOfHoursPerLearner = numberOfHours / learners.length;
- Create an abstract
People
class- The class signature should be parameterized with
PersonType
such thatPersonType
is a sub class ofPerson
. - The class should implement
Iterable
of typePersonType
. - Upon construction
People
should consume aList
ofPersonType
and set it to a respectivepersonList
field. - The class should define a constructor which consumes a variable number of
PersonType
objects and sets thepersonList
field respectively. - The class should define a method named
add
which adds aPersonType
to thepersonList
. - The class should define a method named
remove
which removes aPersonType
from thepersonList
. - The class should define a method named
size
which returns the size ofpersonList
. - The class should define a method named
clear
which clears ourpersonList
field. - The class should define a method named
addAll
which adds anIterable
ofPersonType
objects to the compositepersonList
.- This method will NOT take an argument of
Collection<PersonType>
- This method will NOT take an argument of
- The class should define a method named
findById
which makes use of along id
parameter to return aPersonType
object with the respectiveid
field. - The class should define a method named
findAll
which returns the compositepersonList
.
- The class signature should be parameterized with
- Create a
Students
class.- The class should be a subclass of
People
of parameterized typeStudent
. - The class should consume a variable number of
Student
objects upon construction and pass them to the super constructor.
- The class should be a subclass of
- Create a
Instructors
class.- The class should be a subclass of
People
of parameterized typeInstructor
. - The class should consume a variable number of
Instructor
objects upon construction and pass them to the super constructor.
- The class should be a subclass of
- Create a
Classroom
class.- The class should consume and set composite reference to an
Instructors
andStudents
object upon construction - The class should define a method
hostLecture
which makes use of aTeacher teacher, double numberOfHours
parameter to host alecture
to the compositepersonList
field in thestudents
reference.
- The class should consume and set composite reference to an
- Each of the following
Config
classes should have a class-signature annotation of@Configuration
- this annotation tells spring to scan for
@Bean
definitions within the scope of the class, and register them to the IOC Container forInject
andAutowire
use later.
- this annotation tells spring to scan for
- Classroom should define getters for each of its fields.
-
@Autowired
- injects bean by type
- can be used alone.
- If is used alone, it will be wired by type
- If more than one bean of same type are declared in the container
@Autowired
does not know which beans to use for injection.
-
@Qualifier
- injects bean by specified name
- supports fields, setter, constructors and multi-argument methods injection
- together with
@Autowired
, clarifies which beans to be wired by specifying the bean name (wired by name)
- Note: The creation of this class will demonstrate an implementation of bean registration in Spring.
- The class should define a method named
currentStudents()
which returns aStudents
representative of the current cohort of students.- the method should be annotated with
@Bean(name = "students")
- this ensures the Spring container registers the bean with the respective name.
- a
@Bean
whosename
attribute is not specified defaults to the name of the method it is annotating.
- the method should be annotated with
- The class should define a bean named
previousStudents()
which returns aStudents
representative of the previous cohort of students.
- The class should define a bean named
tcUsaInstructors()
which returns anInstructors
representative of the Tech Connect USA instructors. - The class should define a bean named
tcUkInstructors()
which returns anInstructors
representative of the Tech Connect UK instructors. - The class should define a bean named
instructors
which returns allInstructors
employed at ZipCodeWilmington- annotate this bean with
@Primary
- this ensures Spring will inject this bean in the case that an
Autowire
annotation is not supplied with aQualifier
annotation
- this ensures Spring will inject this bean in the case that an
- annotate this bean with
- The class should define a bean named
currentCohort()
which returns aClassroom
object whose dependencies areinstructors
andstudents
- The class should define a bean named
previousCohort()
which returns anClassroom
object whose dependencies areinstructors
andpreviousStudents
- Note: it is sometimes useful (although not always necessary) to use the
@DependsOn
annotation to help the Spring framework and other readers of the code to understand what order beans should be executed.@DependsOn({"instructors", "students"})
- Each of the following
Test
classes should be annotated with@RunWith(SpringRunner.class)
- enforces which strategy
junit
should use to run tests
- enforces which strategy
@SpringBootTest
- indicates that this class is a Spring Boot test class
- provides support to scan for a
ContextConfiguration
that tells the test class how to load theApplicationContext
. - If no
ContextConfiguration
classes are specified as a parameter to the@SpringBootTest
annotation, the default behavior is to load theApplicationContext
by scanning for a@SpringBootConfiguration
annotation on a class in the package root.
- Each bean can be injected into the class scope using
@Autowired
along with@Qualifier(name = "beanname")
- Create a
TestStudentConfig
class in thetest
package. - The class should ensure that each
Bean
in theStudentConfig
class is configured as expected. - Tip: You can use the
toString
method to get a representation of the aggregate state of anyPeople
object.
- Create a
TestInstructorConfig
class in thetest
package. - The class should ensure that each
Bean
in theTestInstructorConfig
class is configured as expected.
- Create a
TestClassroomConfig
class in thetest
package. - The class should ensure that each
Bean
in theTestClassroomConfig
class is configured as expected.
- Annotating a class signature with
@Component
allows Spring to register the class as aBean
implicitly.
- Create an
Alumni
component which autowiresStudents
of the previous cohort andInstructors
- Create an
executeBootcamp
method which teaches eachStudent
in the compositeStudents
atotalNumberOfHours
of1200
.- Annotate this method with
@PostConstruct
- denotes that this method must be executed before the class is put into an IoC container
- Annotate this method with
- Create a getter for each of the fields.
-
Write a test class which ensures that each
Student
in theAlumni
class has been taught1200
hours upon injection of theAlumni
dependency. -
Ensure the
numberOfHoursTaught
has been evenly distributed amongst each of the instructors. -
Tip: How to derive
numberOfHoursTaught
dynamically
int numberOfInstructors = instructors.size();
int numberOfStudents = students.size();
double numberOfHoursToTeachEachStudent = 1200;
double numberOfHoursToTeach = numberOfHoursToTeachEachStudent * numberOfStudents;
double numberOfHoursPerInstructor = numberOfHoursToTeach / numberOfInstructors;