问题描述:
- 初学者新接触到
Spring
容器的时候,总是各种懵。 - 不知道对象为什么可以在想要的地方,直接
@Autowired
一下,就可以用。 - 这篇文章就是通俗的讲讲,如何做到用
@Autowired
就可以获得想要的对象。
先想一想为什么要引入Spring
容器?
- 在实际的开发工作中,开发人员需要编写很多
Class
去完成一个功能的编写,完成一个事务的处理。 - 要使用一个
Class
去干活,我们先得new
一个这个Class
的实例对象对吧,会向JVM
(Java Virtual Machine)申请空间,然后才可以执行Class
中编写的非静态代码段。 - 如果没有
Spring
容器,那么每次new
出来的对象干完活,是不是得释放掉呀,避免占用空间对吧。
那么问题就来了,这样重复的对常用的Class去new对象,去释放对象,反而不如就让这些常用的Class保留一个对象对系统的资源开销小。于是Spring
容器,应运而生。就是为了解决此处的开发痛点而出现的。
Spring
容器的通俗理解:
Spring
容器的实际作用,老师们都应该讲过,就是一个承装对象的东西。- 具体点,比如:可以将
Spring
容器理解为一个工具箱,工具箱里面可以有锤子、钳子、扳手、卷尺等等。
其实Spring
容器,也就主要干了三事情。
- 创建并保留对象实例。
- 给对象实例打上标记管理起来。
- 提供给外部通过实例对象的标记获取对象的接口。
实践,干!不怂:
下面来用简单的代码实现一个非常粗犷的Spring容器吧,跟着看一遍,就能懂了。
编码准备:
java JDK1.8
版本IDE
工具,首选IntelliJ IDEA
(这个要收费,有点小贵,当然破解的方法我是不会告诉你们的,我公开是支持正版的),或者Eclipse
,不建议用MyEclipse
准备几个Class:
自定义注册注解:
package com.example.demo.annotation;
import java.lang.annotation.*;
/**
* Created by CN94740284 on 2/9/2020.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyComponent {
}
自定义绑定注解:
package com.example.demo.annotation;
import java.lang.annotation.*;
/**
* Created by CN94740284 on 2/9/2020.
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
}
注册和数据绑定器:
/**
* Created by CN94740284 on 11/20/2020.
*/
public class Register {
private static Container container = new Container();
private static Container getContainer() {
return container;
}
private static boolean regist(Class<?> clzz){
Container container = Register.getContainer();
Map<String, Object> tools = container.getTools();
Object o = null;
try {
o = clzz.newInstance();
tools.put(clzz.getName(),o);
return true;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
private static boolean myAutowired(){
Map<String, Object> tools = Register.getContainer().getTools();
tools.forEach((key,value)->{
Class<?> clzz = value.getClass();
Field[] fs = clzz.getDeclaredFields();
try {
bindFields(value, fs, tools);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return true;
}
public static <T> T getBean(Class<T> clzz){
Map<String, Object> tools = Register.getContainer().getTools();
T t = (T) tools.get(Test.class.getName());
return t;
}
private static boolean bindFields(Object obj,Field[] fields,Map<String, Object> tools) throws IllegalAccessException {
for (Field field : fields) {
//获取属性上T类型的注解
if(field.isAnnotationPresent(MyAutowired.class)) {
Class<?> type = field.getType();
Object tool = tools.get(type.getName());
if(tool!=null){
field.setAccessible(true);
field.set(obj,tool);
}else{
return false;
}
}
}
return true;
}
public static boolean registAndAutoBind(ScanFileTool t) {
t.findClassLocal(ScanFileTool.STARATEGY_PATH);
List<Class<? extends String>> eleStrategyList = t.getEleStrategyList();
// 注册对象
if(eleStrategyList!=null && eleStrategyList.size()>0){
eleStrategyList.forEach((clzz)->{
if(clzz.isAnnotationPresent(MyComponent.class)){
Register.regist(clzz);
}
});
}
// 绑定属性对象
Register.myAutowired();
return true;
}
}
使用@MyComponent注解:
package com.example.demo.tools;
import com.example.demo.annotation.MyComponent;
/**
* Created by CN94740284 on 11/20/2020.
*/
@MyComponent
public class Hamer extends Tool {
}
准备抽象类:
package com.example.demo.tools;
import com.alibaba.fastjson.JSON;
/**
* Created by CN94740284 on 11/20/2020.
*/
public abstract class Tool {
public String getToolName() {
return getClass().getName();
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
使用自定义注解@MyComponent注册,使用@MyAutowired绑定注入数据
package com.example.demo.tools.test;
import com.example.demo.annotation.MyAutowired;
import com.example.demo.annotation.MyComponent;
import com.example.demo.tools.Hamer;
/**
* Created by CN94740284 on 11/20/2020.
*/
@MyComponent
public class Test {
@MyAutowired
private Hamer hamer;
public void printHamerName(){
System.out.println("Test : "+hamer.getToolName());
}
}
以上方法和类的放心食用方式:
package com.example.demo;
import com.example.demo.register.Register;
import com.example.demo.tools.test.Test;
import com.example.demo.utils.ScanFileTool;
import java.net.URISyntaxException;
public class DemoApplication {
public static void main(String[] args) throws URISyntaxException {
// 根据包路径扫描含有自定义注解的对象
ScanFileTool t = new ScanFileTool();
// 注册并绑定
boolean b = Register.registAndAutoBind(t);
// 类似SpringUtils.getBean
Test test = Register.getBean(Test.class);
// 调用对象方法
test.printHamerName();
}
}
流程如下:
相关代码下载链接:点此下载