Wechat public number: Orange Pine Java technology nest article first gold platform, the subsequent synchronous update of the public number, after attention to reply to “plus group” can join the Internet technology exchange & push group, and a group of big factory leaders to discuss interview questions. Reply to “666” to get all the information packages available on the First line Internet (including development software, development specifications, classic e-PDF, and some quality learning courses).
preface
Spring IOC is a core component of the Spring framework, inversion of Control (IOC). For those who are new to Spring, the design concept of IOC may be very superficial. The key to understanding IOC is to understand who controls whom and what. Why is it a reversal? What has been reversed?
Who controls who and what? Remember when you were learning servlets and creating objects inside each layer with the new keyword, remember that this is the program actively creating dependent objects; And when you get to Spring IoC has a container for creating these objects, controlling objects.
Why is it a reversal? The simple understanding is that when we actively control to get dependent objects, this is a positive transformation, right? In inversion, the container helps create and inject dependent objects. Why reverse? Because the container helps us find and inject the dependent object, the object only passively accepts the dependent object, so it is inversion; What has been reversed? The retrieval of dependent objects has been reversed.
Hand-tear the simplest IOC container
Maybe you don’t get it, think it’s abstract? Follow the bloggers hand in hand to achieve IOC!
The implementation here is just a handwritten understanding of ioc concepts
demo
.ioc
There are a lot of details waiting for us to learn. If you are interested, you can go to the official account to read an article about it published beforespring ioc
Source read the article
Ioc is not a container. Ok, let’s define a container first. The characteristics of a container must have objects to store and fetch
Spring objects are beans, but we do not know what the bean type is, so the generic representation, and when the bean is stored in the container. Spring does an initial scan at startup, so we define an initAutoWired method to emulate that.
Start by defining a tangerine container interfaceJsContainer
.
Description: Need source file plus QQ group [572411121] free request */
public interface JsContainer {
/** * get Bean * from Class@param clazz
* @return* /
<T> T getBean(Class<T> clazz);
/** * Register a Class to the container **@param clazz
*/
Object registerBean(Class
clazz);
/** ** */
void initAutoWired(a);
Copy the code
Let’s write another custom annotation identifierJsAutowired
To get the instantiation later by reflectionbean
Custom annotations can specify the type to be injected, as well as the injectedbean
The name.
package com.orangesongjava.ioc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
Description: Need source file plus QQ group [572411121] free request */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsAutowired {
/ * * *@returnThe class type to inject */Class<? > value()default Class.class;
/ * * *@returnThe bean name */
String name(a) default "";
}
Copy the code
Now that we have the container interface and annotations, let’s think about implementing it! Let’s define a classJsSampleContainer
To implement the container interfaceJsContainer
。
package com.orangesongjava.ioc;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Description: Need source file plus QQ group [572411121] free request */
@SuppressWarnings("unchecked")
public class JsSampleContainer implements JsContainer {
/** * Save all bean objects in the format of com.xxx.xxx.xxxclass: @56x2ya */
private Map<String, Object> beanNameMap;
/** * Store the relationship between bean and name */
private Map<String, String> beanKeys;
public JsSampleContainer(a) {
this.beanNameMap = new ConcurrentHashMap<>();
this.beanKeys = new ConcurrentHashMap<>();
}
@Override
public <T> T getBean(Class<T> clazz) {
String name = clazz.getName();
Object object = beanNameMap.get(name);
if(null! = object){return (T) object;
}
return null;
}
@Override
public Object registerBean(Class
clazz) {
String name = clazz.getName();
beanKeys.put(name, name);
Object bean = newInstance(clazz);
beanNameMap.put(name, bean);
return bean;
}
@Override
public void initAutoWired(a) {
beanNameMap.forEach((k,v) -> injection(v));
}
/** * Inject object *@param object
*/
public void injection(Object object) {
// All fields
try {
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
// The fields to be injected
JsAutowired jsAutowired = field.getAnnotation(JsAutowired.class);
if (null! = jsAutowired) {// The field to be injected
Object autoAutoWiredField = null;
String name = jsAutowired.name();
// If the JsAutowired custom annotation does not specify the name attribute, the default value is "".
if(! name.equals("")) {// Specify a specific name
String className = beanKeys.get(name);
if(null! = className && ! className.equals("")){
autoAutoWiredField = beanNameMap.get(className);
}
if (null == autoAutoWiredField) {
throw new RuntimeException("Unable to load "+ name); }}else {
// JsAutowired annotations have no name attribute
// Check whether the injected type is a Class
if(jsAutowired.value() == Class.class){
autoAutoWiredField = register(field.getType());
} else {
// Specify the class to assemble
autoAutoWiredField = this.getBean(jsAutowired.value());
if (null== autoAutoWiredField) { autoAutoWiredField = register(jsAutowired.value()); }}}if (null == autoAutoWiredField) {
throw new RuntimeException("Unable to load " + field.getType().getCanonicalName());
}
boolean accessible = field.isAccessible();
field.setAccessible(true); field.set(object, autoAutoWiredField); field.setAccessible(accessible); }}}catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch(IllegalAccessException e) { e.printStackTrace(); }}private Object register(Class
clazz){
if(null! = clazz){return this.registerBean(clazz);
}
return null;
}
/** * Create an instance object *@paramClazz class object *@return* /
public static Object newInstance(Class
clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null; }}Copy the code
Test the
Let’s test it now. Let’s define a class OrangeSongJavaService so that the test can be called later. Note that there are no annotations on this class. That is, it is not managed by Spring.
Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;
public class OrangeSongJavaService {
public void writeArticleOnJs(String name){
System.out.println(name + "Writing on the Nuggets!"); }}Copy the code
A mock call to OrangeSongJavaClient in the definition of a local call. Note that this class also has no annotations on it, and the OrangeSongJavaService reference is identified by our custom JsAutowired annotation.
Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;
public class OrangeSongJavaClient {
@JsAutowired
private OrangeSongJavaService orangeSongJavaService;
public void work(a) {
orangeSongJavaService.writeArticleOnJs("Orange pine Java");
}
public OrangeSongJavaService getOrangeSongJavaService(a) {
returnorangeSongJavaService; }}Copy the code
Now let’s write a test main method to test it.
Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;
public class IocTest {
private static JsSampleContainer jsContainer = new JsSampleContainer();
public static void main(String[] args) {
// Inject the class into the container
jsContainer.registerBean(OrangeSongJavaClient.class);
// Initialize injection - scan references
jsContainer.initAutoWired();
// The container gets the bean
OrangeSongJavaClient client jsContainer.getBean(OrangeSongJavaClient.class);
/ / executionclient.work(); }}Copy the code
If the output execution logic, it indicates that the program is ok. Sure enough, no problem. See here, is your understanding of IOC a little clear? If you have any questions or do not understand, please leave a comment below. Bloggers give you answers.
Well, I’ll see you next time.
The last
- The article is original, original is not easy, thanks for digging gold platform, feel harvest, help three lianha, thank you
- Wechat search public number: Orange pine Java technology nest, make a friend, into the Internet technology exchange group
- All code, sequence diagrams and architecture diagrams involved in the article are shared and can be requested free of charge through the public account plus group
- If the article has the error, welcome the comment message points out, also welcome to reprint, trouble to mark the source is good