All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jquicker.context.JQuickerContext Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
package com.jquicker.context;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;

import com.jquicker.annotation.ioc.Autowired;
import com.jquicker.annotation.ioc.Qualifier;
import com.jquicker.annotation.stereotype.Component;
import com.jquicker.annotation.stereotype.Repository;
import com.jquicker.annotation.stereotype.Service;
import com.jquicker.annotation.timer.Scheduled;
import com.jquicker.annotation.timer.Task;
import com.jquicker.annotation.tx.Transactional;
import com.jquicker.aop.Advice;
import com.jquicker.commons.other.IDFactory;
import com.jquicker.commons.scanner.ClassFinder;
import com.jquicker.commons.scanner.filter.AnnotationFilter;
import com.jquicker.commons.util.PathUtils;
import com.jquicker.commons.util.StringUtils;
import com.jquicker.context.bean.Bean;
import com.jquicker.context.bean.BeanFactory;
import com.jquicker.context.bean.BeanManager;
import com.jquicker.context.bean.ProxyFactory;
import com.jquicker.exception.BeanCreationException;
import com.jquicker.exception.InjectionException;
import com.jquicker.persistent.rdb.dao.DaoProxyFactory;
import com.jquicker.persistent.rdb.executor.SQLExecutor;
import com.jquicker.persistent.rdb.executor.ExecutorFactory;
import com.jquicker.persistent.rdb.tx.TransactionAdvice;
import com.jquicker.persistent.rdb.tx.TransactionAspect;
import com.jquicker.persistent.rdb.tx.TransactionManager;
import com.jquicker.timer.TimerManager;
import com.jquicker.timer.TimerTask;

public class JQuickerContext {

	private Map> beans = new ConcurrentHashMap>();
	
	private static JQuickerContext jQuickerContext;
	
	private JQuickerContext() {}
	
	public synchronized static JQuickerContext newInstance() {
		if(jQuickerContext == null) {
			jQuickerContext = new JQuickerContext();
		}
		return jQuickerContext;
	}
	
	/**
	 * 初始化依赖注入
	 * 
	 * @author OL
	 * @throws IOException 
	 * @throws InjectionException 
	 */
	public void init() throws IOException, BeanCreationException, InjectionException {
		
		ClassFinder finder = new ClassFinder(new AnnotationFilter(Component.class, Task.class), PathUtils.getClasspath());
		
		List> list = finder.findClass();
		for (Class clazz : list) {
			Object object = BeanFactory.createIntance(clazz);
			String name = StringUtils.toLowerCaseFirstLetter(clazz.getSimpleName());
			if(clazz.isAnnotationPresent(Service.class)) {
				Service service = clazz.getAnnotation(Service.class);
				name = service.value().length() > 0 ? service.value() : name;
			}
			if(clazz.isAnnotationPresent(Repository.class)) {
				Repository repository = clazz.getAnnotation(Repository.class);
				name = repository.value().length() > 0 ? repository.value() : name;
			}
			if(clazz.isAnnotationPresent(Component.class)) {
				Component component = clazz.getAnnotation(Component.class);
				name = component.value().length() > 0 ? component.value() : name;
			} else {
				// 还有@Controller等,在mvc包中处理
			}
			
			if(clazz.isAnnotationPresent(Task.class)) {
				this.processTask(clazz);
			}
			
			BeanManager.putBean(name, object);
			
			// 为@Service创建动态代理,实现事务控制
			if(clazz.isAnnotationPresent(Service.class)) {
				boolean isTransactional = false;
				if(clazz.isAnnotationPresent(Transactional.class)) {
					isTransactional = true;
				} else {
					Method[] methods = clazz.getDeclaredMethods();
					for (Method method : methods) {
						if(method.isAnnotationPresent(Transactional.class)) {
							isTransactional = true;
							break;
						}
					}
				}
				if(isTransactional) {
					// 申明一个切面Aspect
					TransactionAspect aspect = new TransactionManager();
					// 创建一个 Advice
					Advice advice = new TransactionAdvice(object, aspect);
					// 为目标.对象生成代理对象
					Object proxy = ProxyFactory.newProxyInstance(object, advice);
					BeanManager.addProxy(name, proxy);
				}
			}
			
			// 为@Repository创建动态代理的实现类
			if(clazz.isAnnotationPresent(Repository.class)){
				if(object == null && clazz.isInterface()){
					Object proxy = DaoProxyFactory.newProxyInstance(clazz);
					BeanManager.addProxy(name, proxy);
				}
			}
		}
		
		beans = BeanManager.getBeans();
		for (Map.Entry> entry : beans.entrySet()) {
			Bean bean = entry.getValue();
			Object object = bean.getObject();
			if(object != null){
				this.inject(object);
			}
			
		}
	}

	/**
	 * 注入属性
	 * 
	 * @param object 依赖注入的对象
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @author OL
	 */
	private void inject(Object object) throws InjectionException {
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			if(field.isAnnotationPresent(Resource.class)) {
				this.injectByResource(field, object);
			} else if(field.isAnnotationPresent(Autowired.class)){
				this.injectByAutowired(field, object);
			}
		}
	}
	
	private void injectByResource(Field field, Object object) throws InjectionException {
		Object instance = null;
		Resource resource = field.getAnnotation(Resource.class);
		String name = resource.name();
		Class type = resource.type();
		if(name.length() == 0 && type == Object.class) {
			name = field.getName();
			Bean bean = beans.get(name);
			if(bean != null){
				instance = bean.getBean();
			} else {
				List> tmp = this.findBeanByType(field.getType());
				if(tmp.size() == 1) {
					instance = tmp.get(0).getBean();
				} else if(tmp.size() > 1){
					throw new InjectionException("Ambiguous bean of type " + field.getType().getName() + "] is defined: expected single matching bean but found " + tmp.size());
				}
			}
		} else if(name.length() > 0 && type != Object.class) {
			Bean bean = beans.get(name);
			if(bean != null && bean.getType() == type) {
				instance = bean.getBean();
			} else {
				throw new InjectionException("No qualifying bean of type [" + field.getType().getName() + "]  is defined: expected single matching bean but found 0");
			}
		} else if(name.length() > 0) {
			Bean bean = beans.get(name);
			if(bean != null){
				instance = bean.getBean();
			}
		} else if(type != Object.class) {
			List> tmp = this.findBeanByType(type);
			if(tmp.size() == 1) {
				instance = tmp.get(0).getBean();
			} else if(tmp.size() > 1){
				throw new InjectionException("Ambiguous bean of type " + field.getType().getName() + "] is defined: expected single matching bean but found " + tmp.size());
			}
		}
		field.setAccessible(true);
		try {
			field.set(object, instance);
		} catch (Exception e) {
			throw new InjectionException(e);
		}
	}
	
	private void injectByAutowired(Field field, Object object) throws InjectionException {
		Object instance = null;
		Class type = field.getType();
		if(type == SQLExecutor.class) {
			instance = ExecutorFactory.createSQLExcutor();
		} else {
			Qualifier qualifier = field.getAnnotation(Qualifier.class);
			if(qualifier != null && qualifier.value().length() > 0) {
				String name = qualifier.value();
				Bean bean = beans.get(name);
				if(bean != null && bean.getType() == type) {
					instance = bean.getBean();
				} else {
					throw new InjectionException("No qualifying bean of type [" + field.getType().getName() + "]  is defined: expected single matching bean but found 0");
				}
			} else {
				List> tmp = this.findBeanByType(type);
				if(tmp.size() == 0) {
					Autowired autowired = field.getAnnotation(Autowired.class);
					if(autowired.required()) {
						throw new InjectionException("No qualifying bean of type " + field.getType().getName() + "]  is defined: expected single matching bean but found 0");
					}
				} else if(tmp.size() > 1){
					throw new InjectionException("Ambiguous bean of type " + field.getType().getName() + "] is defined: expected single matching bean but found " + tmp.size());
				} else {
					instance = tmp.get(0).getBean();
				}
			}
		}
		field.setAccessible(true);
		try {
			field.set(object, instance);
		} catch (Exception e) {
			throw new InjectionException(e);
		}
	}
	
	/**
	 * 根据类型查找bean
	 * @param type
	 * @return
	 * @author OL
	 */
	private List> findBeanByType(Class type){
		Collection> collection = beans.values();
		List> list = new ArrayList>();
		for (Bean bean : collection) {
			if(type.isAssignableFrom(bean.getType())) {
				list.add(bean);
			}
		}
		return list;
	}
	
	/**
	 * 处理定时任务类
	 * @param clazz
	 * @author OL
	 */
	private void processTask(Class clazz){
		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			if(method.isAnnotationPresent(Scheduled.class)){
				Scheduled scheduled = method.getAnnotation(Scheduled.class);
				TimerTask timer = new TimerTask();
				timer.setId(IDFactory.newGUID());
				timer.setName(scheduled.name());
				timer.setClazz(clazz);
				timer.setMethod(method);
				timer.setPeriod(scheduled.period());
				timer.setCron(scheduled.cron());
				timer.setFirst(scheduled.first());
				timer.setLast(scheduled.last());
				timer.setLimit(scheduled.limit());
				timer.setPolicy(scheduled.policy());
				timer.setConcurrent(scheduled.concurrent());
				timer.setDescription(scheduled.description());
				timer.setEnable(scheduled.enable());
				TimerManager.add(timer);
			}
		}
	}
	
}