河南网站建设的详细策划,电子商务网站建设试题 答案,美的企业微信网站,个人网站备案与企业备案Spring之手写一个依赖注入容器 1. 创建两个自定义注解1.1 Component注解1.2 DI注解 2. ApplicationContext接口与实现类2.1 ApplicationContext 接口2.2 实现类#xff1a;DefaultListableApplicationContext 3. 定义DAO层和Service层及其实现4. 定义异常信息类4.1 InjectBean… Spring之手写一个依赖注入容器 1. 创建两个自定义注解1.1 Component注解1.2 DI注解 2. ApplicationContext接口与实现类2.1 ApplicationContext 接口2.2 实现类DefaultListableApplicationContext 3. 定义DAO层和Service层及其实现4. 定义异常信息类4.1 InjectBeanException4.2 NotExistsBean4.3 NotSupportMoreSuperInterface 5. 测试自定义bean容器(带依赖注入)5.1 新建测试类TestUser5.2 输出结果 1. 创建两个自定义注解
1.1 Component注解
Target(value ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
public interface Component {String value() default ;
}1.2 DI注解
Target(value ElementType.FIELD)
Retention(RetentionPolicy.RUNTIME)
public interface DI {String value() default ;}2. ApplicationContext接口与实现类
2.1 ApplicationContext 接口
public interface ApplicationContext {// 获取beanObject getBean(String name);// 获取beanT T getBean(String name, ClassT clazz);// 判断bean是否存在boolean exists(String name);boolean exists(String name, Class? clazz);
}2.2 实现类DefaultListableApplicationContext
// 实现类
public class DefaultListableApplicationContext implements ApplicationContext {/*** 存放bean对象容器*/private MapString, Object objectsMap new ConcurrentHashMap(128);private MapClass, Object objectsTypeMap new ConcurrentHashMap(128);private Logger log LoggerFactory.getLogger(DefaultListableApplicationContext.class);// 扫描的基础路径private String basePath;public DefaultListableApplicationContext(String basePackage) {//public static void pathDemo1(String basePackageName){String packagePath basePackage.replaceAll(\\., \\\\);try {URL url Thread.currentThread().getContextClassLoader().getResource(packagePath);if (StringUtils.hasText(url.getPath())) {String filePath URLDecoder.decode(url.getFile(), UTF8);// 扫描的基础路径basePath filePath.substring(0, filePath.length() - packagePath.length());//包扫描loadBeans(new File(filePath));// 依赖注入loadDI();}} catch (IOException e) {throw new RuntimeException(e);}}OverrideNullablepublic Object getBean(String name) {return objectsMap.get(name);}OverrideNullablepublic T T getBean(String name, ClassT clazz) {Object obj objectsMap.get(name);if (obj null) {Object bean;if ((bean objectsTypeMap.get(clazz)) null) {for (Class? interfaceClazz : clazz.getInterfaces()) {if ((bean objectsTypeMap.get(interfaceClazz)) ! null)return (T) bean;getBean(name, interfaceClazz);}return null;}return (T) bean;}return clazz.isInstance(obj) ? clazz.cast(obj) : null;}Overridepublic boolean exists(String name) {return objectsMap.get(name) null ? false : true;}Overridepublic boolean exists(String name, Class? clazz) {if (objectsMap.get(name) null) {if (objectsTypeMap.get(clazz) null) {for (Class? interfaceClazz : clazz.getInterfaces()) {if (objectsTypeMap.get(interfaceClazz) ! null)return true;exists(name, interfaceClazz);}return false;}return true;}return true;}/*** 包扫描** param file*/private void loadBeans(File file) {// 1 判断当前文件是否文件夹if (file.isDirectory()) {File[] childrenFiles file.listFiles();// 2. 获取文件夹里面的所有内容// 3. 判断文件夹为空直接返回if (childrenFiles null || childrenFiles.length 0) {return;}// 4. 如果文件夹不为空遍历文件夹内容for (File childFile : childrenFiles) {// 4.1 遍历得到每个file对象继续判断。如果是文件夹递归if (childFile.isDirectory()) {loadBeans(childFile);} else {// 4.2 遍历得到的file不是文件夹是文件// 4.3 得到包路径 类名称部分// C:/desktop/IdeaProjects/spring-mytest/src/main/java/com/ypy/contextString pathWithClass childFile.getAbsolutePath().substring(basePath.length() - 1);// 4.4 判断当前文件类型是否为.classif (pathWithClass.endsWith(.class)) {// 4.5 如果是.class类型把路径\替换成., 把.class去掉// com.ypy.context.beans.UserServiceImplString allName pathWithClass.replaceAll(\\\\, .).replace(.class, );// 4.6 使用反射实例化try {Class? clazz Class.forName(allName);if (!clazz.isInterface()) {// 4.6.1 判断是否有Component注解,有if (clazz.getAnnotation(Component.class) ! null) {Object instance clazz.getConstructor().newInstance();// 优先使用用户自定义的bean名称if (StringUtils.hasText(clazz.getAnnotation(Component.class).value())) {String beanName clazz.getAnnotation(Component.class).value();objectsMap.put(beanName, instance);log.warn( objectsMap store bean(name,obj) ( beanName , instance ));if (clazz.getInterfaces().length 1) {objectsTypeMap.put(clazz.getInterfaces()[0], instance);log.warn( objectsTypeMap store bean(class,obj) ( clazz.getInterfaces()[0].getSimpleName() , instance ));} else if (clazz.getInterfaces().length 0) {objectsTypeMap.put(clazz, instance);log.warn( objectsTypeMap store bean(class,obj) ( clazz.getInterfaces()[0].getSimpleName() , instance ));} else {throw new NotSupportMoreSuperInterface(Not support the bean that has more than two super interfaces.);}}// 其次使用父接口的类名作为bean名称else if (clazz.getInterfaces().length 0) {String interfaceName clazz.getInterfaces()[0].getSimpleName();String beanName lowercaseFirstLetter(interfaceName);// 放入容器中objectsMap.put(beanName, instance);log.warn( objectsMap store bean(name,obj) ( beanName , instance ));// 可能出现bugobjectsTypeMap.put(clazz.getInterfaces()[0], instance);log.warn( objectsTypeMap store bean(class,obj) ( clazz.getInterfaces()[0].getSimpleName() , instance ));}// 如果说没有父接口,就使用类名作为bean名称else {String beanName lowercaseFirstLetter(clazz.getSimpleName());// 放入容器中objectsMap.put(beanName, instance);log.warn( objectsMap store bean(name,obj) ( beanName , instance ));objectsTypeMap.put(clazz, instance);log.warn( objectsTypeMap store bean(class,obj) ( clazz.getInterfaces()[0].getSimpleName() , instance ));}}}} catch (Exception e) {throw new RuntimeException(e);}}}}}}private void loadDI() {for (Map.EntryString, Object entry : objectsMap.entrySet()) {Object obj entry.getValue();Class? clazz obj.getClass();Field[] fields clazz.getDeclaredFields();for (Field field : fields) {try {field.setAccessible(true);if (field.getAnnotation(DI.class) ! null) {Class?[] interfaces field.getType().getInterfaces();String needWiredBeanName;Object autoWiredBean;// 优先使用注解DI的value注入if (StringUtils.hasText(needWiredBeanName field.getAnnotation(DI.class).value())) {autoWiredBean objectsMap.get(needWiredBeanName);if (autoWiredBean ! null) {field.set(obj, autoWiredBean);log.warn( DI: Class clazz.getSimpleName() of field named field.getName() is injected with value of autoWiredBean from objectsMap, by value of annotation DI);continue;} /*else {throw new NotExistsBean(Not exists the bean named needWiredBeanName to inject as property);}*/}// 没有父接口needWiredBeanName lowercaseFirstLetter(field.getType().getSimpleName());if ((autoWiredBean objectsMap.get(needWiredBeanName)) ! null || (autoWiredBean objectsTypeMap.get(field.getType())) ! null) {field.set(obj, autoWiredBean);log.warn( DI: Class clazz.getSimpleName() of field named field.getName() is injected with value of autoWiredBean , by value or type of property itself );continue;}// 使用父接口的名字从bean容器中查找注入if (interfaces.length 0) {for (Class? interfaceClazz : interfaces) {String interfaceClazzName interfaceClazz.getSimpleName();if (interfaceClazz.isAssignableFrom(field.getType())) {needWiredBeanName lowercaseFirstLetter(interfaceClazzName);if ((autoWiredBean objectsMap.get(needWiredBeanName)) ! null || (autoWiredBean objectsTypeMap.get(interfaceClazz)) ! null) {field.set(obj, autoWiredBean);log.warn( DI: Class clazz.getSimpleName() of field named field.getName() is injected with value of autoWiredBean , by value or type of super interface);}}}continue;}throw new InjectBeanException(There occurs an Exception while injecting property filed [ field.getName() ] of Class clazz.getSimpleName() , because bean factory doesnt exist the bean named needWiredBeanName);}} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}}private String lowercaseFirstLetter(String name) {return name.substring(0, 1).toLowerCase() name.substring(1);}}
3. 定义DAO层和Service层及其实现
// 3.1 dao层
public interface UserDao {void addUser(User user);
}/**
* userDao实现
*/
Component(userDao)
public class UserDaoImpl implements UserDao {Overridepublic void addUser(User user) {System.out.println();System.out.println(------------------执行UserDaoImpl中的addUser方法开始------------------);System.out.println(\t\t\t\t\t\t名字\t\t\t\t年龄);System.out.println(\t\t\t\t\t\tuser.getName()\t\t\t\tuser.getAge());System.out.println(------------------执行UserDaoImpl中的addUser方法完毕------------------);}
}// 3.2 service层public interface UserService {void add();
}// service实现
Component(userService)
public class UserServiceImpl implements UserService {DI(userDao)private UserDaoImpl userDao;Overridepublic void add() {System.out.println(》》》 user service impl execute add method...);User user new User(张三, 25);userDao.addUser(user);}
}
4. 定义异常信息类
4.1 InjectBeanException
public class InjectBeanException extends RuntimeException{public InjectBeanException() {super();}public InjectBeanException(String message) {super(message);}
}4.2 NotExistsBean
public class NotExistsBean extends RuntimeException{public NotExistsBean() {}public NotExistsBean(String message) {super(message);}
}4.3 NotSupportMoreSuperInterface
public class NotSupportMoreSuperInterface extends RuntimeException{public NotSupportMoreSuperInterface() {super();}public NotSupportMoreSuperInterface(String message) {super(message);}
}5. 测试自定义bean容器(带依赖注入)
5.1 新建测试类TestUser
public class TestUser {public static void main(String[] args) {DefaultListableApplicationContext context new DefaultListableApplicationContext(com.ypy.context);UserService userService context.getBean(aaa, UserServiceImpl.class);UserDao userDao context.getBean(userDaoImpl, UserDao.class);boolean existFlag context.exists(aaa/*, UserService.class*/);System.out.println(UserService exists ? existFlag);System.out.println(从Bean容器中获取aaa对象地址: userService);System.out.println(从Bean容器中获取userDao对象地址: userDao);userService.add();}
}5.2 输出结果
一月 18, 2024 4:01:20 上午 com.sun.org.slf4j.internal.Logger warn
警告: objectsMap store bean(name,obj) (userDao,com.ypy.context.dao.impl.UserDaoImpl2b193f2d)
一月 18, 2024 4:01:20 上午 com.sun.org.slf4j.internal.Logger warn
警告: objectsTypeMap store bean(class,obj) (UserDao,com.ypy.context.dao.impl.UserDaoImpl2b193f2d)
一月 18, 2024 4:01:20 上午 com.sun.org.slf4j.internal.Logger warn
警告: objectsMap store bean(name,obj) (userService,com.ypy.context.service.impl.UserServiceImpl7a81197d)
一月 18, 2024 4:01:20 上午 com.sun.org.slf4j.internal.Logger warn
警告: objectsTypeMap store bean(class,obj) (UserService,com.ypy.context.service.impl.UserServiceImpl7a81197d)
一月 18, 2024 4:01:20 上午 com.sun.org.slf4j.internal.Logger warn
警告: DI: Class UserServiceImpl of field named userDao is injected with value of com.ypy.context.dao.impl.UserDaoImpl2b193f2d from objectsMap, by value of annotation DI
UserService exists ? false
从Bean容器中获取aaa对象地址: com.ypy.context.service.impl.UserServiceImpl7a81197d
从Bean容器中获取userDao对象地址: com.ypy.context.dao.impl.UserDaoImpl2b193f2d
》》》 user service impl execute add method...------------------执行UserDaoImpl中的addUser方法开始------------------名字 年龄张三 25
------------------执行UserDaoImpl中的addUser方法完毕------------------Process finished with exit code 0