要实现的功能:
- 将对象的实例化交给自定的ioc容器.
- 通过注解的方式对接口进行依赖注入
- 通过getBean("userName")方法那到对象,使用对象的方法
-
首先,创建一个对象,定义对象的构造函数
package cn.lisongyu.ioc.demo.bean; import cn.lisongyu.ioc.annotation.Component; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.bean.UserBean * @description userbean * @create 2018年11月22日 11:08 */ @Component //自定义的组件,让ioc容器扫描带有指定注解的类,将当前类装配到ioc容器中 public class UserBean { @Autowired //自定义的注入注解 private Service service; public UserBean() { System.out.println("UserBean -> instance"); } public void getUser(){ service.test(); //接口的方法,如果注入失败,将报空指针异常 System.out.println("用户详情展示"); } }
package cn.lisongyu.ioc.demo.a.b.c; import cn.lisongyu.ioc.annotation.Component; import cn.lisongyu.ioc.demo.a.b.Service; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.a.b.c.TestService * @description Service实现类 * @create 2018年11月22日 11:22 */ @Component public class TestService implements Service { public TestService() { System.out.println("TestService -> instance"); } @Override public void test() { System.out.println("Service 接口实现方法"); } }
package cn.lisongyu.ioc.demo.a.b; /** * /** * * @author lisongyu * @ClassName cn.lisongyu.ioc.demo.a.b.Service * @description Service接口 * @create 2018年11月22日 17:31 */ public interface Service { void test(); }
-
创建自定义的注解
package cn.lisongyu.ioc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //依赖注入注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) //只能注解到字段上 public @interface Autowired { }
package cn.lisongyu.ioc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //组件注解 @Retention(RetentionPolicy.RUNTIME) //程序运行时执行 @Target(ElementType.TYPE) //该注解指定标注的位置 TYPE:类 public @interface Component { }
-
定义一个接口,用来获取bean对象的方法
package cn.lisongyu.ioc.context; /** * /** * Application 接口 * @author lisongyu * @ClassName cn.lisongyu.ioc.context.Application * @description * @create 2018年11月22日 11:24 */ public interface Application { Object getBean(String beanName); }
package cn.lisongyu.ioc.context; import cn.lisongyu.ioc.annotation.Component; import java.io.File; import java.io.FileFilter; import java.net.URL; import java.sql.SQLOutput; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.concurrent.ConcurrentHashMap; /** * @author lisongyu * @ClassName cn.lisongyu.ioc.context.ApplicationImpl * @description Application的实现类 * @create 2018年11月22日 11:24 */ public class ApplicationImpl implements Application { //定义存放所有类对象的集合 private List<Class<?>> classList = new ArrayList<>(); //定义存放类的实例对象的集合 private Map<String,Object> instanceMap = new ConcurrentHashMap<>(); //无参构造 public ApplicationImpl() { } /** * 有参构造,通过传入的包路径来实现扫描 * @param basePackage */ public ApplicationImpl(String basePackage) { //扫描包路径 doScan(basePackage); //实例化 doIoc(); System.out.println(instanceMap); //依赖注入 doDi(); } /** * 实例化对象 */ private void doIoc() { //首先判断一下当前类集合中是否含有元素 if (classList == null){ return; } //遍历集合 classList.forEach((clz) ->{ try { //通过类对象,实例化一个对象 Object instance = clz.newInstance(); //创建key String key = getKeyName(clz.getSimpleName()); //存放到map集合中 //如果集合中存在则报错 if (instanceMap.containsKey(key)){ throw new RuntimeException("相同的类名"); } //放入ioc容器中 instanceMap.put(key,instance); //判断当前类是否实现了接口 Class<?>[] interfaces = clz.getInterfaces(); for (Class<?> inter : interfaces) { instanceMap.put(inter.getName(),instance); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }); } //改名,获取一个首字母小写的类名 private String getKeyName(String simpleName) { char[] chars = simpleName.toCharArray(); chars[0] += 32; return String.valueOf(chars); } //依赖注入 private void doDi() { //首先判断实例对象是否有 if (instanceMap.size() == 0) return; //遍历所有的实例对象 instanceMap.forEach((k,v) -> { Object instance = v; //注入实体对象 Object injectionInstance = null; //通过反射获取类对象 Class<?> clz = v.getClass(); //获取当前类对象的所有声明的字段 Field[] fields = clz.getDeclaredFields(); //循环遍历所有字段 for (Field field : fields) { //判断字段是否含有@Autowired注解 if(field.isAnnotationPresent(Autowired.class)){ String name = field.getType().getName(); injectionInstance = this.instanceMap.get(name); } // 通过反射注入到该属性中 field.setAccessible(true); try { field.set(instance,injectionInstance); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); } //包扫描方法 private void doScan(String basePackage) { //获取当前包的位置 URL resource = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")); //创建一个文件对象 File file = new File(resource.getPath()); //遍历文件 File[] fileNames = file.listFiles(new FileFilter() { @Override public boolean accept(File childFile) { //判断当前文件是否是一个文件夹 if (childFile.isDirectory()){ //如果是文件夹,递归,获取所有的class文件 doScan(basePackage+"."+childFile.getName()); }else { //判断当前文件是否是一个类文件 if (childFile.getName().endsWith(".class")){ String classPath = basePackage + "." + childFile.getName().replaceAll("\\.class", ""); Class<?> clz = null; try { clz = Class.forName(classPath); //判断是否是有@Component注解的类 if (clz.isAnnotationPresent(Component.class)){ classList.add(clz); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return false; } }); } @Override public Object getBean(String beanName) { return this.instanceMap.get(beanName); } }
-
运行main()
package cn.lisongyu.ioc; import cn.lisongyu.ioc.context.Application; import cn.lisongyu.ioc.context.ApplicationImpl; import cn.lisongyu.ioc.demo.bean.UserBean; import java.util.*; /** * Hello world! * */ public class App { public static void main( String[] args ) { //包路径 Application app = new ApplicationImpl("cn.lisongyu.ioc.demo"); UserBean userBean = (UserBean) app.getBean("userBean"); userBean.getUser(); } }
-
结果:
TestService -> instance //接口实现类的初始化 UserBean -> instance //对象类的初始化 {cn.lisongyu.ioc.demo.a.b.Service=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, testService=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, userBean=cn.lisongyu.ioc.demo.bean.UserBean@6d03e736} //装配到容器中的类 Service 接口实现方法 //service.test(); 用户详情展示 //userBean.getUser();