總共大概分為這幾步:有空再補上實現(xiàn)過程的描述
直接上代碼:整體工程就是這樣簡單过椎,項目不引用spring
1婆排、首先是程序入口AppConfig(主要設(shè)置掃描路徑)
@ComponentScan("cn.service")
public class AppConfig {
}
2腋颠、自定義四個注解:@Autowired伊磺,@ComponentScan肆捕,@Scope和@Service
3掌实、定義bean類OrderService和UserService分別在類上加上注解@Service
@Service("orderService")
public class OrderService {
@Autowired
? ? private UserServiceuserService;
? ? public void getUserService(){
System.out.println(userService);
? ? }
}
@Service("userService")
@Scope("prototype")
public class UserService {
}
4、定義AnnotationConfigApplication實例化听想、初始化bean腥刹,填充屬性并將bean寫入單例池
public class AnnotationConfigApplication {
private ConcurrentHashMapbeanDefinitionMap =new ConcurrentHashMap();
? ? private ConcurrentHashMapsingletonObjects =new ConcurrentHashMap();
? ? /**
? ? ? * @Description 根據(jù)啟動配置類加載初始化
? ? ? *
? ? ? * @Param classConfig
? ? ? * @Return
? ? ? * @Author 胡攀
? ? ? */
? ? public AnnotationConfigApplication(Class classConfig) {
//掃描類
? ? ? ? List classes = scan(classConfig);
? ? ? ? //掃描到類之后,解析這個類汉买,Service,BeanDefinition
? ? ? ? for (Class clazz : classes) {
Service service = (Service) clazz.getAnnotation(Service.class);
? ? ? ? ? ? String name = service.value();
? ? ? ? ? ? //獲取Scope注解
? ? ? ? ? ? BeanDefinition beanDefinition =new BeanDefinition();
? ? ? ? ? ? beanDefinition.setClassBean(clazz);
? ? ? ? ? ? if(clazz.isAnnotationPresent(Scope.class)) {
Scope scope = (Scope) clazz.getAnnotation(Scope.class);
? ? ? ? ? ? ? ? beanDefinition.setScope(scope.value());
? ? ? ? ? ? }else{
beanDefinition.setScope("singleton");
? ? ? ? ? ? }
beanDefinitionMap.put(name, beanDefinition);
? ? ? ? }
//遍歷beanDefinitionMap生成bean
? ? ? ? //單例bean直接存到單例池
? ? ? ? for (String beanName :beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition =beanDefinitionMap.get(beanName);
? ? ? ? ? ? if (beanDefinition.getScope().equals("singleton")) {
//生成這個bean
? ? ? ? ? ? ? ? Object bean = createBean(beanDefinition);
? ? ? ? ? ? ? ? singletonObjects.put(beanName,bean);
? ? ? ? ? ? }
}
}
/**
? ? * @Description 創(chuàng)建一個bean
*
? ? * @Param beanDefinition
? ? * @Return Object
? ? * @Author 胡攀
? ? */
? ? private ObjectcreateBean(BeanDefinition beanDefinition){
//生成這個bean
? ? ? ? Class beanClass = beanDefinition.getClassBean();
? ? ? ? //實例化
? ? ? ? try {
Object bean = beanClass.getDeclaredConstructor().newInstance();
? ? ? ? ? ? //填充屬性
? ? ? ? ? ? Field[] fields = beanClass.getDeclaredFields();
? ? ? ? ? ? for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
Object attr = getBean(field.getName());
? ? ? ? ? ? ? ? ? ? field.setAccessible(true);
? ? ? ? ? ? ? ? ? ? field.set(bean, attr);
? ? ? ? ? ? ? ? }
}
return bean;
? ? ? ? }catch (InstantiationException e) {
e.printStackTrace();
? ? ? ? }catch (IllegalAccessException e) {
e.printStackTrace();
? ? ? ? }catch (InvocationTargetException e) {
e.printStackTrace();
? ? ? ? }catch (NoSuchMethodException e) {
e.printStackTrace();
? ? ? ? }
return null;
? ? }
/**
? ? * @Description 通過beanName 獲取單例池中的bean
*
? ? * @Param beanName
? ? * @Return
? ? * @Author 胡攀
? ? */
? ? public ObjectgetBean(String beanName) {
BeanDefinition beanDefinition =beanDefinitionMap.get(beanName);
? ? ? ? if("prototype".equals(beanDefinition.getScope())){
return createBean(beanDefinition);
? ? ? ? }else{
Object bean =singletonObjects.get(beanName);
? ? ? ? ? ? if(bean ==null){
Object o = createBean(beanDefinition);
? ? ? ? ? ? ? ? singletonObjects.put(beanName,o);
? ? ? ? ? ? ? ? return o;
? ? ? ? ? ? }else{
return bean;
? ? ? ? ? ? }
}
}
/**
? ? * @Description 根據(jù)啟動類掃描類
? ? *
? ? * @Param classConfig
? ? * @Return
? ? * @Author 胡攀
? ? */
? ? private Listscan(Class classConfig) {
List classList =new ArrayList();
? ? ? ? //掃描類
? ? ? ? ComponentScan componentScan = (ComponentScan) classConfig.getAnnotation(ComponentScan.class);
? ? ? ? String scanPath = componentScan.value();
? ? ? ? scanPath = scanPath.replace(".", "/");
? ? ? ? System.out.println("scanPath:" + scanPath);
? ? ? ? //如何掃描類
? ? ? ? ClassLoader classLoader = AnnotationConfigApplication.class.getClassLoader();
? ? ? ? URL resource = classLoader.getResource(scanPath);
? ? ? ? System.out.println("resource:" + scanPath);
? ? ? ? //獲取文件路徑下的所有文件路徑
? ? ? ? File file =new File(resource.getFile());
? ? ? ? File[] files = file.listFiles();
? ? ? ? for (File f : files) {
//替換為classLoader能識別的包路徑
? ? ? ? ? ? String absolutePath = f.getAbsolutePath();
? ? ? ? ? ? absolutePath = absolutePath.substring(absolutePath.indexOf("cn"), absolutePath.indexOf(".class")).replace("\\", ".");
? ? ? ? ? ? try {
Class clazz = classLoader.loadClass(absolutePath);
? ? ? ? ? ? ? ? System.out.println(clazz);
? ? ? ? ? ? ? ? if (clazz.isAnnotationPresent(Service.class)) {
classList.add(clazz);
? ? ? ? ? ? ? ? }
}catch (ClassNotFoundException e) {
e.printStackTrace();
? ? ? ? ? ? }
}
return classList;
? ? }
}
5衔峰、最后調(diào)用的結(jié)果就是這樣:注意scope注解單例和原型的判斷方式