IOC의 원칙과 IOC의 사용자 정의 함수를 달성하기위한 프레임 워크 (A)

IOC 소개

IOC는 사실,이 두 가지 개념은 다음 의존성 주입의 도입이 이해를 촉진하기 위하여 이해의 용이성을 위해, 모호의이 같은 제어의 반전은 학술 용어이며, 또한 의존성 주입으로 알려진 제어의 반전 (Inversion of Control에)을 의미합니다.

왜 사용 IOC

대형 프로젝트를 결합 할 때 사용하지 않을 IOC에서 프로그램을 업데이트 할 때, 종종 직접 원래의 부품을 유지하기 위해, 원래의 기능을 삭제하지, 기존의 클래스를 대체하는 새로운 클래스를 사용할 필요가 있지만,이 방법 모든 관련 클래스를 수정해야이는 IOC 클래스와 클래스 디커플링은 디커플링 층이 하나를 변경해야 도달하는 동안 매우 번잡하고 변화를 잊고, 그것은 오류가 발생하지, 프로그램을 실행할 수 없습니다 달성 될 수있다 그것은 쉽게 확장을 유지하기 위해, 전체 프로젝트를 업데이트 할 수 있습니다.

IOC 달성하는 방법

디커플링의 목적 대상물 반사기를 주입하기 위해 인터페이스를 사용할 필요성을 달성하기 위해,

두 클래스와 테스트 클래스를 작성하십시오

//User类
public class User {
    private UserDAO userDAO;
     public UserDAO getUserDAO() {
        return userDAO;
    }
}

//UserDAO类
public class UserDAO {
}
//测试类
public class Demo {
    public static void main(String[] args) {
        User user = new User();
        user.getUserDAO();
    }
}

지금은이 두 클래스와 같은 다른 요구가있는 경우, 관계는, 다음 먼저 주입하는 반사를 사용하는 더 많은 변화 대신 UserDAO, 다음은 이전 사용자 및 데모에 따라 수정해야합니다 새로운 UserDAO1를 만들려면 UserDAO 및 UserDAO1이 IUserDAO을 구현할 수 있도록하고, 사용자 클래스의 속성이 IUserDAO하게하자

public class User {
    private IUserDAO userDAO;

    public IUserDAO getUserDAO() {
        return userDAO;
    }

반사 데모 분사 클래스에서 userDAO1

 public static void main(String[] args) throws Exception {
        User user = new User();
        //如果要更换UserDAO类,只需要添加一个新的类让他实现IuserDAO,这里修改一下就可以了
        IUserDAO userDAO = new UserDAO1();
        //通过反射取得UserDAO的属性并把要更改的类的实例注入
        Class<? extends User> aClass = user.getClass();
        Field field = aClass.getDeclaredField("userDAO");
        field.setAccessible(false);
        field.set(user,userDAO);
    }

이를 위해, 확실히 나는 하나 하나를 얻을 수있는 코드의 라인으로 새로운 개체로 이동합니다 너무 많은 문제가 싫어,하지만 많은 같은 큰 프로젝트 하나 하나 그것을 발견 할 경우, 궁금해? 경우에 누출, 그 버그를 발견합니다. 그리고이 쓰기 만 한 번 더 클래스 후, 더 많은 프로젝트는에이 하나를 사용할 수 있습니다.

2. 심지어 주사를 속성 수있는 많은 방법이있다?

그리고 처음 두 속성, 코멘트 MyField를 사용자 정의 주석을 사용하여 기본값을 준

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyField {
     Class name() default Class.class;
     String value() default "";
}

그 후 주입되는 특성에 주석을 추가 한 값이 요구되는 주입을 더한

public class User {
    
    @MyField(name = UserDAO1.class)
    public IUserDAO userDAO;
    
    @MyField(value = "张三")
    public String name;
    
    
    public IUserDAO getUserDAO() {
        return userDAO;
    }
}

데모에서 사용자의 요소를 주입하는

public static void main(String[] args) throws Exception {
        User user = new User();
        //遍历获取user中的所有元素
        Field[] declaredFields = user.getClass().getDeclaredFields();
        for (Field field:declaredFields){
            MyField annotation = field.getAnnotation(MyField.class);
            //判断元素上面是否有MyFiled注解
            if (annotation != null){
                //如果有就获取name和value的值
                Class userDAO1 = annotation.name();
                String name = annotation.value();
                //如果name的值不为空,且不等于默认值,就说明需要注入,直接注入
                if (userDAO1!=null && !userDAO1.equals(Class.class)){
                    field.set(user,userDAO1.newInstance());
                }
                //如果value值不为空且不等于默认值,就说明需要注入,直接注入
                if(name!=null && !name.equals("")){
                    field.set(user,name);
                }
            }
        }
        System.out.println(user);
    }

출력은 User{userDAO=com.qf.demo.UserDAO1@511d50c0이, 이름 = '조 스미스'}입니다
지침 주입에 성공, 지금 우리는 UserDAO가 발견 변경하려면 당신은 단지 음의 값,하지만 엄밀히 말하면 메모를 수정하려면 자바 코드가, 그것이 의미하는 것입니다하지 디커플링의 목적을 달성하기 위해 자바 코드를 변경할 필요가 없습니다.

3.뿐만 아니라 사용자 클래스를 주입하기 위해, 많은 유형이있다?

사실, 원칙, 나는 모든 클래스를 주입 한 다음 전체 폴더, 모든 자바 파일에 대한 액세스를 통과 할 필요에서 사용자 정의 주석 SpringComponent을 같은 추가되는 클래스는 분사 이상 작성 SpringComponent에 직접 주석이됩니다 방법

public static void main(String[] args) throws Exception {
        Injection injection = new Injection();
        injection.init("com.qf.demo");

    }

    public void init(String packageName) throws Exception {
        String basePath="D:\\program\\idea\\day52_demo\\src\\main\\java\\";
        //将传入的"com.qf.demo"转换成"com\qf\demo"
        String replace = packageName.replace(".", "/");
        File file = new File(basePath + "\\"+replace);
        //遍历该文件夹下所有文件
        File[] files = file.listFiles();
        for (File f:files){
            String name = f.getName();
            if(f.isFile()){
                //只有java文件才是哦们需要的,如果是文件就判断是不是以".java"结尾的
                if (name.endsWith(".java")){
                    //如果是就以“.”将文件名分割成"demo"和"java"两部分
                    String[] split = name.split("\\.");
                    String className = split[0];
                    Class<?> aClass = Class.forName(packageName +"." +className);
                  //判断类上是否有SpringComponent注解,如果有就调用inject方法,将类对象传入
                    SpringComponent annotation = aClass.getAnnotation(SpringComponent.class);
                    if (annotation != null){
                        inject(aClass);
                    }
                }
            }else{
                //如果不是文件就是文件夹,就使用递归循环该方法
                String childPath=packageName+"."+name;
                init(childPath);
            }
        }

    }

    public <T>void inject(Class<T> clazz) throws Exception {
        //创建传入类对象的实例对象
        T t = clazz.newInstance();
        Field[] declaredFields = clazz.getClass().getDeclaredFields();
        for (Field field:declaredFields){
            MyField annotation = field.getAnnotation(MyField.class);
            //判断元素上面是否有MyFiled注解
            if (annotation != null){
                //如果有就获取name和value的值
                Class aClass = annotation.name();
                String name = annotation.value();
                //如果name的值不为空,且不等于默认值,就说明需要注入,直接注入
                if (aClass!=null && !aClass.equals(Class.class)){
                    field.set(t,aClass.newInstance());
                }
                //如果value值不为空且不等于默认值,就说明需要注入,直接注入
                if(name!=null && !name.equals("")){
                    field.set(t,name);
                }
            }
        }
    }

종결

이제 IOC는 가장 기본적인 기능을 달성했다,하지만 같은 많은 단점, 있기는하지만 :
1. 당신이 주소 basePath를 변경할 필요가 새 프로젝트 만들 때마다
2. 내가 개체 내에서 요소를 취하거나 새 대상을 먹고 싶어 말을하고, 전자는 구별이 부족
A가 B의 요소이며, B와 첫 번째 구현하는의 다음 B가 비어있는 경우 3.
...

출시 두 원저 · 원의 칭찬 0 · 조회수 (110)

추천

출처blog.csdn.net/weixin_46007540/article/details/103499554