Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
MacFJA committed May 17, 2017
0 parents commit 600d58a
Show file tree
Hide file tree
Showing 11 changed files with 1,512 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Created by .ignore support plugin (hsz.mobi)
### Maven template
target/
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The MIT License (MIT)

Copyright (c) 2017 [MacFJA](https://github.com/MacFJA)

> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
154 changes: 154 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Injector

- [Injection possibility](#injection)
- [Constructor Injection](#injection-constructor)
- [Setters Injection](#injection-setters)
- [Properties Injection](#injection-properties)
- [Method Injection](#injection-method)
- [Injection types](#types)
- [Installation](#installation)
- [Examples](#examples)
- [Declaring a mapping](#examples-mapping)
- [For a singleton](#examples-mapping-singleton)
- [For an interface/abstract class to concrete implementation](#examples-mapping-interface)

## Injection possibility<a id="injection"></a>

This library offer several types of injection:

- Constructors injection
- Setters injection
- Properties injection
- Method injection

### Constructor Injection<a id="injection-constructor"></a>

The constructor injection try to create a class instance by looping over every class constructor until it found one that can be used .

The injection criteria are:

- Parameters are not Java primitive
- Parameters packages are in injector package list
- All parameters constructor do the same

### Setters Injection<a id="injection-setters"></a>

The setter injection is automatically run after the constructor injection if the injector have the option activated.
(Can be also be call on an existing instance)
For a setter method to be injected, it must validate the following conditions:

- The method name **MUST** start with `set`
- The method **MUST** have exactly one parameter
- The method **MUST** have the annotation `@javax.inject.Inject`
- The method parameter must be an injectable class

### Properties Injection<a id="injection-properties"></a>

The property injection is automatically run after the constructor injection if the injector have the option activated.
(Can be also be call on an existing instance)
For a property to be injected, it must validate the following conditions:

- The property **MUST** be accessible
- The property **MUST** have the annotation `@javax.inject.Inject`
- The property must be an injectable class

### Method Injection<a id="injection-method"></a>

A method can have its parameters injected.

There are two way to inject parameters in a method.
First one is with a `java.lang.reflect.Method` object, in this case there are no control, if a parameter can't be injected `null` will be used.
The second way is to use the method name, with this way, all method of the object with this name will be try, and the method must have the annotation `@javax.inject.Inject` and every parameters must be injectable.

## Injection types<a id="types"></a>

There are two injection types:

- Singleton
- Every times a new instance

## Installation<a id="installation"></a>

Clone the project:
```
git clone https://github.com/MacFJA/Injector.git
```
Install the project into your local Maven repository:
```
cd Injector/
mvn clean
mvn install
```
Remove the source:
```
cd ..
rm -r Injector/
```
Add the depency in your Maven project:
```xml
<project>
<!-- ... -->
<dependencies>
<!-- ... -->
<dependency>
<groupId>io.github.macfja</groupId>
<artifactId>injector</artifactId>
<version>1.0.0</version>
</dependency>
<!-- ... -->
</dependencies>
<!-- ... -->
</project>
```

## Examples<a id="examples"></a>

### Declaring a mapping<a id="examples-mapping"></a>

#### For a singleton<a id="examples-mapping-singleton"></a>

```java
io.github.macfja.injector.Injector injector = new io.github.macfja.injector.Injector("mypackage");
injector.addMapping(new mypackage.MyClass());
// ... later
injector.get(mypackage.MyClass.class); // return the instance created in addMapping method
// ... later
injector.get(mypackage.MyClass.class); // still the same instance
```

or

```java
io.github.macfja.injector.Injector injector = new io.github.macfja.injector.Injector("mypackage");
injector.addMapping(mypackage.MyClass.class, new io.github.macfja.injector.InjectionUnit(new mypackage.MyClass()));
// ... later
injector.get(mypackage.MyClass.class); // return the instance created in addMapping method
// ... later
injector.get(mypackage.MyClass.class); // still the same instance
```

or

```java
io.github.macfja.injector.Injector injector = new io.github.macfja.injector.Injector("mypackage");
injector.addMapping(
mypackage.MyClass.class,
new io.github.macfja.injector.InjectionUnit(
mypackage.MyClass.class,
io.github.macfja.injector.InjectionUnit.Instantiation.Singleton
)
);
// ... later
injector.get(mypackage.MyClass.class); // return the instance created in addMapping method
// ... later
injector.get(mypackage.MyClass.class); // still the same instance
```

#### For an interface/abstract class to concrete implementation<a id="examples-mapping-interface"></a>

```java
io.github.macfja.injector.Injector injector = new io.github.macfja.injector.Injector("mypackage");
injector.addMapping(mypackage.MyInterface.class, new io.github.macfja.injector.InjectionUnit(/* ... */));
// ... later
injector.get(mypackage.MyInterface.class); // return an instance according to the InjectionUnit
```
50 changes: 50 additions & 0 deletions doc/Example1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Example 1

This example is a case where method injection is used (differing class loading).

This approach can also be used for lazy loading.

```java
package example;

class PanelA extends javax.swing.JPanel {
// Do your stuff
}

class PanelB extends javax.swing.JPanel {
// Do other stuff
}

class Application extends javax.swing.JFrame {
private static io.github.macfja.injector.Injector injector = new io.github.macfja.injector.Injector("example");

public static void main(String[] args) {
injector.addMapping(
Application.class,
new io.github.macfja.injector.InjectionUnit(
Application.class,
io.github.macfja.injector.InjectionUnit.Instantiation.Singleton
)
);

injector.get(Application.class);

}

public Application(PanelA panel) {
setContentPane(panel);
setVisible(true);

new java.util.Timer().schedule(new java.util.TimerTask() {
@Override
public void run() {
injector.injectIntoMethodName(Application.this, "init");
}
}, 1000);
}

public void init(PanelB panelB) {
setContentPane(panelB);
}
}
```
78 changes: 78 additions & 0 deletions doc/Example2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Example 2

This example show the interface use case.

```java
package example;
interface ServiceInterface {
void connect();
void disconnect();
void doAction(String param);
}
class Application {
private ServiceInterface service;
public static io.github.macfja.injector.Injector injector;

public static void main(String[] args) {
injector = new io.github.macfja.injector.Injector("example");
injector.addMapping(
ServiceInterface.class,
new io.github.macfja.injector.InjectionUnit(
SocketService.class,
io.github.macfja.injector.InjectionUnit.Instantiation.Singleton
)
);

injector.get(Application.class);

}

public Application(ServiceInterface service) {
this.service = service;

doStuff();
}


public void doStuff() {
service.connect();
service.doAction("first");
service.doAction("second");
service.disconnect();
}
}

class SocketService implements ServiceInterface {
@Override
public void connect() {
// Open socket
}

@Override
public void doAction(String param) {
// Send data in socket
}

@Override
public void disconnect() {
// Close socket
}
}

class FileService implements ServiceInterface {
@Override
public void connect() {
// Open file stream
}

@Override
public void doAction(String param) {
// Write in file
}

@Override
public void disconnect() {
// Close file stream
}
}
```
51 changes: 51 additions & 0 deletions doc/Mapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Mapping

A mapping is a rule that indicate the _Injector_ how to handle a class.

There are several mapping:

- The singleton mapping (for a given class, the same instance is always return)
- The interface to implementation (when the interface is requested a new instance of a defined class is provided)
- The interface to singleton (when the interface is requested a singleton is provided)
- The parent to child (when requested, a new instance of the defined class children is returned)
- The parent to child singleton (when requested, a singleton of the defined class children is returned)

## Interface and parent mapping

The **interface to implementation**, the **interface to singleton**, the **parent to child** and the **parent to child singleton** are base on the same principle.
The method `addMapping` is used in its form:
```
public void addMapping(Class, InjectionUnit)
```
Where the first parameter is the interface/parent and the second contains information about implementation/child/singleton.

```
| First parameter | Second parameter
-----------------------------+-------------------+------------------------------------------------------------------------------
interface to implementation | MyInterface.class | new InjectionUnit(MyImpl.class, InjectionUnit.Instantiation.NewInstance)
interface to singleton | MyInterface.class | new InjectionUnit(MyImpl.class, InjectionUnit.Instantiation.Singleton)
interface to singleton | MyInterface.class | new InjectionUnit(new MyImpl())
parent to child | MyAbstract.class | new InjectionUnit(MyExtender.class, InjectionUnit.Instantiation.NewInstance)
parent to child singleton | MyAbstract.class | new InjectionUnit(MyExtender.class, InjectionUnit.Instantiation.Singleton)
parent to child singleton | MyAbstract.class | new InjectionUnit(new MyExtender())
```

## Singleton mapping

There are 3 way to declare a Singleton:

```
injector.addMapping(new MySingleton());
```

```
injector.addMapping(MySingleton.class, new InjectionUnit(new MySingleton()));
// or
injector.addMapping(MyInterface.class, new InjectionUnit(new MyImplementation()));
```

```
injector.addMapping(MySingleton.class, new InjectionUnit(MySingleton.class, InjectionUnit.Instantiation.Singleton));
// or
injector.addMapping(MyInterface.class, new InjectionUnit(MyImplementation.class, InjectionUnit.Instantiation.Singleton));
```
Loading

0 comments on commit 600d58a

Please sign in to comment.