Java Development Frameworks
There is a lot of development frameworks for Java. This post talks about Guice (for Dependency Injection design pattern implementation), Spring (Java integration environment), JUnit and Mockito (for unit test).
Dependency Injection (DI)
DI is design pattern. When an object A depends on another object B, DI means to pass a built object B to object A from outside of A instead of letting object A create the object B.
Using DI pattern to organize code could decouple the classes and make it eaiser for testing. There are some libraries and framework could help to implement the DI pattern. e.g. Guice
Guice
Guice is Googal’s framework to let your application use DI pattern. To use Guice, you needs to following elements.
- Java class constructors that are annoated with
@Inject
- Guice modules where binding the dependency class to the instance or other subclass without dependency. Module class needs to extend
AbstractModule
- Guice injector created based on the Guice modules in the main function. Then the main function could use the injector to get the instance of an object. The injector will resolve the dependencies according to the configuration.
Concepts
- Key: to identify a dependency that can be resolved
- e.g.
@Message String
is a kind ofKey<String>
- e.g.
- Provider: represent factories that are capable of creating objects to satisfy dependency requirements
- e.g.
interface Provider<T> { T get(); }
- e.g.
The Guice module is a collections of Map<Key>, Provider>>, which means it bind a lot of dependencies with real objects.
@Inject
to mark required injection
The @Inject
annotation could describe a class’s constructor, function, or field. Once the content is annotated by @Inject
, Guice could inject the dependency to the class automatically.
1 | class Test { |
The data1
, data2
, and data3
could be injected by Guice when the class Test
is institated, and there is no need to use code to set those field to class Test
Guice Module class
Guice Module is a class whose name ends with Module
. In this class, those classes used as dependency of other classes are binded to a specific object. Thus when those classes have dependencies of others (and have been annoated by Inject
), Guice can use this Guice Module class to provide a built object to the classes.
Use bind function to bind a class to other class
- Usually bind a base class / interface to a sub class without dependency or an instance
- Could use annotation to classify different class. So that the same class could be bonded to different target
1 | // Note that the BaseClass is the dependency of a class. SubClass is the type |
Use @Provides
1 | // This bind the int class to the xxx |
Use Provider
1 | bind(int.class).toProvider(MyCustomizedProvider) |
Use Guice to get instance of class
1 | Injector inject = createInjector( |
If DataType
has dependencies of other classes, injector will check whether the class of dependencies have been bind to a specific object. If it is, then pass that object to DataType
Unit Test
Unit test is the test for method of classes. It guides the development process and this kind of process is known as Test-driven Development (TDD).
JUnit is an open-source framework for unit test
JUnit
JUnit uses the following annotations to comment functions to achieve different functions
@Test
: indiciate the function is a unit test@ParameterizedTest
: give parameters to the test case@MethodSource
: indicate using the static function to get parameters@ValueSource()
: indicate the parameters@CsvSource()
@CscFileSource()
- Some conditions used with
@Test
@Disabled
: let JUnit skip this test case@EnableOnOs()
@EnableOnJre()
@Before
: do actions before performing the tests@BeforeEach
@BeforeAll
@After
: do tear down work after performing the tests@AfterEach
@AfterAll
In unit test function, Assertion
is often used
assertEquals()
assertTrue()
assertFalse()
assertThrows()
- …
Mockito
- Mock objects or functions for unit test
- Mock dummy objects
- Mock the return value of a function
- Can work with JUnit
Mock Static Method
- Add
@PrepareForTest
at class level - Call
PowerMockito.mockStatic()
for mocking static class; CallPowerMockito.spy()
for mocking a specific method in the class - Use
Mockito.when().thenReturn()
to mock specific method
Maven
A tool for Java project management and construction. It provides
- Standard project structure
- Standard construction pipeline (compile, test, package, release)
- Dependency Management
Maven Project Structure
The pom.xml
file includes the configuration of the project. The most important thing is the groupId
, artifactId
, and version
.
Construction Piepline
Maven has a lifecycle to mark the status of the project. The lifecycle includes several phase, from validate to compile and to test, etc.
Using mvn
command could let the project go into specific phase.
Dependency Management
Maven could resolve the dependency of packages and download the jar
packages automatically. The dependencies includes the following scopes
- compile: require the package during compile
- test: require the packakge during test
- runtime: require the package during runtime but not in compile
- provided: require the package during compile but not in runtime
Spring
Spring is a light development framework. It has the following components
- Core: DI, AOP (Aspect-Oriented Programming), events, resources
- Test: TestContext
- Data Access: JDBC, ORM, OXM
- Web: Spring MVC (MVC: Model, View, Controller), Spring WebFlux Web, Web Socket
- Integration:
- Language: Kotlin, Groovy