# IocFramework **Repository Path**: wchshouji/spring ## Basic Information - **Project Name**: IocFramework - **Description**: 自定义ioc实现 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-11 - **Last Updated**: 2021-08-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring 框架作业 ## 1. 题目: ​ 自定义@Service、@Autowired、@Transactional注解类,完成基于注解的IOC容器(Bean对象创建及依赖注入维护)和声明式事务控制。 1)注解有无value属性值【@service(value="") @Repository(value="")】 2)service层是否实现接口的情况【jdk还是cglib】 ## 2. 解决思路: 1)需要完成@Service、@Autowired、@Transactional三个注解的自定义。 2)扫描指定包下注解,完成类实例化、依赖关系、事务等步骤,并完成工厂初始化。 3)使用注解定义bean方式。 4)测试。 ### 2.1 完成@Service、@Autowired、@Transactional三个注解的自定义 #### 2.1.1 @MyService自定义: ``` java package com.wch.spring.annotation; import java.lang.annotation.*; /** * 自定义Service注解 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyService { String value() default ""; } ``` #### 2.1.2 @MyAutowired自定义: ``` java package com.wch.spring.annotation; import java.lang.annotation.*; /** * 自定义Autowired注解 */ @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyAutowired { boolean value() default true; } ``` #### 2.1.3 @MyTransactional自定义: ``` java package com.wch.spring.annotation; import java.lang.annotation.*; /** * 自定义Transactional注解 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyTransactional { String value() default "TransactionManager"; } ``` ### 2.2 扫描指定包下注解,完成类实例化、依赖关系、事务等步骤,并完成工厂初始化。 #### 2.2.1 导入反射依赖 ~~~ java org.reflections reflections 0.9.11 ~~~ #### 2.2.2 编写bean工厂,完成对象创建 ~~~ java package com.wch.spring.factory; import com.alibaba.druid.util.StringUtils; import com.wch.spring.annotation.MyAutowired; import com.wch.spring.annotation.MyService; import com.wch.spring.annotation.MyTransactional; import org.reflections.Reflections; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 工厂类,生产对象(使用反射技术) */ public class BeanFactory { /** * 1:扫描包,通过反射技术实例化对象并且存储待用(map集合) * 2:对外提供获取实例对象的接口(根据id获取) */ private static Map map = new HashMap<>(); // 存储对象 static { try{ //1、扫描包,通过反射技术实例化对象并且存储(map集合) //通过反射技术,扫描包并获取反射对象集合 Reflections wchs = new Reflections("com.wch.spring"); Set> clazzs = wchs.getTypesAnnotatedWith(MyService.class); //遍历对象集合 for (Class clazz:clazzs) { // 获取实例化对象 Object object = clazz.newInstance(); MyService service = clazz.getAnnotation(MyService.class); //判断MyService注解上是否有自定义对象ID if(StringUtils.isEmpty(service.value())){ //由于getName获取的是全限定类名,所以要分割去掉前面包名部分 String[] names = clazz.getName().split("\\."); map.put(names[names.length-1], object); }else{ map.put(service.value(), object); } } //维护对象之间依赖关系 for(Map.Entry entrySet: map.entrySet()) { Object obj = entrySet.getValue(); Class clazz = obj.getClass(); //获取每个类的所有属性 Field[] fields = clazz.getDeclaredFields(); //遍历属性,确认是否有使用Autowired注解,有使用注解则需要完成注入 for (Field field : fields) { //判断是否使用注解的参数 if (field.isAnnotationPresent(MyAutowired.class) && field.getAnnotation(MyAutowired.class).value()) { //有使用注解则注入 String[] names = field.getType().getName().split("\\."); String name = names[names.length - 1]; Method[] methods = clazz.getMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; if (method.getName().equalsIgnoreCase("set" + name)) { method.invoke(obj, map.get(name)); } } } } //判断当前类是否有Transactional注解,若有则使用代理对象 if(clazz.isAnnotationPresent(MyTransactional.class)){ //获取代理工厂 ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory"); Class[] face = clazz.getInterfaces();//获取类实现的所有接口 //判断对象是否实现接口 if(face!=null&&face.length>0){ //实现使用JDK obj = proxyFactory.getJdkProxy(obj); }else{ //没实现使用CGLIB obj = proxyFactory.getCglibProxy(obj); } } // 把处理之后的object重新放到map中 map.put(entrySet.getKey(),obj); } }catch(Exception e){ e.printStackTrace(); } } // 2:对外提供获取实例对象的接口(根据id获取) public static Object getBean(String id) { return map.get(id); } } ~~~ ### 2.3 使用注解定义bean ​ 使用自定义注解将需要定义的bean添加到spring容器中,并使用自定义注解在需要使用的地方将bean注入。 在service实现类中添加注解MyTransactional事务控制。 ### 2.4 测试