# 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 测试