IOC:
Inverse of Control(控制反转) 将原本在程序中手动创建对象的控制权,交由Spring框架来管理 若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
Github:https://github.com/starcold/StarColdIOC
github只有src下的文件和pom.xml文件,代码带有详细的注释,请自取;
github用不了的可以点这里
项目结构目录如下:
annotation实现一些需要的注解
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.FIELD)//作用在字段上
@Documented
public @interface Autowire {
//注解有一个名为 value 的可选参数。不设置的话默认为“”。如果没有后面的 default "",则表示这是一个必须的参数。不指定的话会报错。
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//作用在类上
@Documented
public @interface Component{
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//作用在类上
@Documented
public @interface Controller {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.PARAMETER)//作用在方法参数上面
@Documented
public @interface RequestParam {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target({ElementType.TYPE, ElementType.METHOD})//作用在类和方法,参考springmvc
@Documented
public @interface RequsetMapping {
String value() default "";
}
support下AnnotationApplicationContext继承了ApplicationContext和BeanRegister;相当于BeanFactory。
Interfaces下定义了两个接口ApplicationContext和BeanRegister
public interface ApplicationContext {
Object getBean(String id);
<T>T getBean(String id, Class<T> clazz);
Map<String, Object> getBeans();
}
public interface BeanRegister {
void registBeanDefinition(List<BeanDefinition> bds);
void registInstanceMapping(String id, Object instance);
}
一些默认的工厂实现
public class BeanCreater{
private BeanRegister register;
public BeanCreater(BeanRegister register){
this.register = register;
}
public void create(List<BeanDefinition> bds){
for(BeanDefinition bd : bds){
doCreate(bd);
}
}
public void doCreate(BeanDefinition bd){
Object instance = bd.getInstance();
this.register.registInstanceMapping(bd.getId(), instance);
}
}
public class BeanDefinition {
private String id;
private Class clazz;
public BeanDefinition(String id, Class clazz){
this.id = id;
this.clazz = clazz;
}
public Object getInstance(){
try{
return clazz.newInstance();
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
//region Getter && Setter
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
//endregion
}
public class BeanDefinitionGenerator {
public static List<BeanDefinition> generte(String classname){
try{
Class clazz = Class.forName(classname);
String[] ids = generateIds(clazz);
if(ids==null){
return null;
}
List<BeanDefinition> list = new ArrayList<BeanDefinition>();
for(String id:ids){
list.add(new BeanDefinition(id, clazz));
}
return list;
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
return null;
}
private static String[] generateIds(Class clazz){
String[] ids = null;
if(clazz.isAnnotationPresent(Controller.class)){
ids = new String[]{clazz.getName()};
}
else if(clazz.isAnnotationPresent(Component.class)){
Component component = (Component) clazz.getAnnotation(Component.class);
String value = component.value();
if(!"".equals(value)){
ids = new String[]{value};
}
else{
Class<?>[] interfaces = clazz.getInterfaces();
ids = new String[interfaces.length];
for(int i = 0; i < interfaces.length; i++){
ids[i] = interfaces[i].getName();
}
return ids;
}
}
return ids;
}
}
public class BeanDefinitionParser {
public static final String SCAN_PACKAGE = "scanPackage";
private BeanRegister register;
public BeanDefinitionParser(BeanRegister register){
this.register = register;
}
public void parse(Properties properties){
String packageName = properties.getProperty(SCAN_PACKAGE);
doRegister(packageName);
}
public void doRegister(String packageName){
URL url = getClass().getClassLoader().getResource("./" + packageName.replace(".","/"));
File dir = new File(url.getFile());
for(File file:dir.listFiles()){
if (file.isDirectory()){
doRegister(packageName + "." + file.getName());
}
else{
String className = packageName + "." + file.getName().replaceAll(".class", "").trim();
List<BeanDefinition> definitions = BeanDefinitionGenerator.generte(className);
if(definitions == null)continue;
this.register.registBeanDefinition(definitions);
}
}
}
}
public class Populator {
public Populator(){
}
public void populator(Map<String, Object> instanceMapping) {
if (instanceMapping.isEmpty()) return;
for (Map.Entry<String, Object> entry : instanceMapping.entrySet()) {
Field[] fields = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowire.class)) continue;
Autowire autowire = field.getAnnotation(Autowire.class);
String id = autowire.value();
if ("".equals(id)) id = field.getType().getName();
field.setAccessible(true);
try {
field.set(entry.getValue(), instanceMapping.get(id));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
最后的测试类
@Controller
public class MyController {
@Autowire("myservice")
private MyService service;
public void test(){
service.print("test success!");
}
public static void main(String[] args){
ApplicationContext context = new AnnotationApplicationContext("applicationContext.properties");
MyController controller = context.getBean("com.starcold.ioc.MyController", MyController.class);
controller.test();
}
}
@Component("myservice")
public class MyService {
public void print(String s){
System.out.println(s);
}
}
参考博客:
Spring源码--IOC容器实现(6)--Bean依赖注入