zoukankan      html  css  js  c++  java
  • spring的ioc技术

    一、了解Spring IOC/DI

      1:Spring有两大核心技术,控制反转(Inversion of Control, IOC)/依赖注入(Dependency Injection,DI)和面向切面编程(Aspect Oriented Programming,AOP)

      2. IOC/DI: 它用来管理所有的java类,类对象的创建和依赖关系都由IOC/DI进行控制。控制反转(IOC)和依赖注入(DI)在spring中表示同一种意思,只是看问题的角度不同,例如

      当在A类中new一个B类时,控制权由A掌握,可以理解为控制正转,当A类使用的B类实例有spring创建时,控制权由spring掌握,就是控制反转;

      依赖注入可以理解为A类依赖于spring,由spring注入B类。控制反转是抽象的概念,只是提出了一种“控制”的方式,而依赖注入是spring框架实现“控制反转”的具体方法。

      3. IOC/DI工作原理:spring IOC/DI的更为直观的叫法是容器,这是因为spring可以管理很多类,当需要某一类对象的实例时,spring就会提供相应的实例,就像是一个容器里面

      可以放入很多东西,需要什么就取什么。那么在spring容器中都有什么类可以使用呢?这需要预先定义在spring的配置文件中,默认的配置文件名称是applicationContext.xml

      例如在配置文件中定义了A类和B类,而A类中使用到了B类,那么配置文件中再定义好这种依赖关系,即可由Spring自动地把B类实例注入到A类中,但是,这种注入是有条件的,

      类需要符合Javabean的定义规范,在A类中需要定义对B类赋值的setter方法。这是Spring对管理的类唯一的要求,不需要像EJB那样实现框架本身的任何接口,也是spring被称

      为轻量级框架的原因。

    二、IOC/DI使用到的技术

      1. JDOM:JDOM是对xml文件进行解析的技术,Spring的配置文件applicationContext.xml就是由JDOM进行解析的,它可以提取出xml文件中定义的标签和属性值。

      1.1 环境的搭建:

      

      1.2 StudentAction.java

    复制代码
    public class StudentAction {
        private StudentService studentService;
    
        public void setStudentService(StudentService studentService) {
            this.studentService = studentService;
        }
        public void printName() {
            System.out.println(studentService.getName());
        }
    }
    复制代码

      1.3 StudentServiceImpl.java

    复制代码
    public class StudentServiceImpl implements StudentService{
        private StudentDao studentDao;
    
        public void setStudentDao(StudentDao studentDao) {
            this.studentDao = studentDao;
        }
    
        public String getName() {
            return studentDao.getName();
        }
    }
    复制代码

      1.4 StudentService.java

    public interface StudentService {
        public String getName();
    }

      1.5 StudentDao.java

    public interface StudentDao {
        public String getName();
    }

      1.6 StudentDaoImpl.java

    public class StudentDaoImpl implements StudentDao{
    
        public String getName() {
            return "Jike Wang";
        }
    }

      1.7 测试

    复制代码
    public class TestAction {
    public static void main(String[] args) {
        //使用ApplicationContext接口的实现类ClassPathXmlApplicationContext加载spring配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
        //通过ApplicationContext接口的getBean方法获取id或name为studentAction的Bean实例
        StudentAction studentAction = (StudentAction) applicationContext.getBean("studentAction");
        //调用方法
        studentAction.printName();
    }
    }
    复制代码

      1.8 使用jdom模拟spring解析xml文件,读取关键信息

      自定义XML代码:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <!-- 定义StudentDaoImpl对象并指定id为studentDao -->
        <bean id="studentDao" class="com.IOC.dao.impl.StudentDaoImpl"></bean>
        <!-- 定义StudentServiceImpl对象并指定id为studentService-->
        <bean id="studentService" class="com.IOC.service.impl.StudentServiceImpl">
            <property name="studentDao" ref="studentDao"></property>
        </bean>
        <!-- 定义StudentAction对象并指定id为studentAction -->
        <bean id="studentAction" class="com.IOC.action.StudentAction">
            <property name="studentService" ref="studentService"></property>
        </bean>
    </beans>
    复制代码
    复制代码
    public class TestJDOM {
    public static void main(String[] args) {
        String path = "src/main/resources/applicationContext.xml";//xml文件目录
        //用于创建文档对象
        SAXBuilder sb = new SAXBuilder();
        //构造的XML文档对象
        Document doc;
        try {
            //创建文档对象
            doc = sb.build(path);
            //得到文档的根元素<beans>
            Element rootElement = doc.getRootElement();
            
            //得到文档的所有<bean>
            List<Element> list = rootElement.getChildren("bean");
            for (Element element : list) {
                //得到<bean>的id属性值
                String id = element.getAttributeValue("id");
                //得到<bean>的class属性值
                String classValue = element.getAttributeValue("class");
                //得到<bean>的子元素<property>
                Element propertyElement = element.getChild("property");
                String propertyName = null;
                String propertyRef = null;
                if (propertyElement != null) {
                    //得到<property>的name属性值
                    propertyName = propertyElement.getAttributeValue("name");
                    //得到property的内容
                    propertyRef = propertyElement.getAttributeValue("ref");
                }
                System.out.println("========================");
                System.out.println("id="+id);
                System.out.println("class="+classValue);
                System.out.println("propertyName="+propertyName);
                System.out.println("propertyRef="+propertyRef);
                System.out.println("========================");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    }
    复制代码

    测试结果:

     2. 反射机制:对配置文件中的类名使用反射机制可以实现类加载初始化等工作,也可以调用类的方法进行属性注入,java.lang.reflect提供了反射相关的工具

    复制代码
    public class TestReflect {
        public static void main(String[] args) {
            //表示StudentDao接口全路径
            String studentDao = "com.IOC.dao.StudentDao";
            //表示StudentService接口全路径
            String studentService = "com.IOC.service.StudentService";
            //表示StudentDaoImpl类全路径
            String studentDaoImpl = "com.IOC.dao.impl.StudentDaoImpl";
            //表示StudentServiceImpl
            String studentServiceImpl = "com.IOC.service.impl.StudentServiceImpl";
            //表示StudentAction类全路径
            String studentAction = "com.IOC.action.StudentAction";
            
            //表示setStudentService方法的字符串
            String setStudentService = "setStudentService";
            //表示setStudentDao方法的字符串
            String setStudentDao = "setStudentDao";
            try {
                //使用全路径字符串加载StudentDao类别
                Class studentDaoClass = Class.forName(studentDao);
                //使用全路径字符串加载StudentService类别
                Class studentServiceClass = Class.forName(studentService);
                //使用全路径字符串加载StudentDaoImpl类别
                Class studentDaoImplClass = Class.forName(studentDaoImpl);
                //使用全路径字符串加载StudentServiceImpl类别
                Class studentServiceImplClass = Class.forName(studentServiceImpl);
                //使用全路径字符串加载StudentAction类别
                Class studentActionClass = Class.forName(studentAction);
                
                //setStudentDao方法签名,相当于获取次此方法,使用类别获取setStudentDao方法
                Method setDaoMethod = studentServiceImplClass.getMethod(setStudentDao, studentDaoClass);
                //setStudentService方法签名,使用类别获取setStudentService方法
                Method setServiceMethod = studentActionClass.getMethod(setStudentService, studentServiceClass);
                
                //创建StudentDaoImpl对象,相当于new StudentDaoImpl(),但返回的是Object对象
                Object studentDaoImplnstance = studentDaoImplClass.newInstance();
                //创建StudentServiceImpl对象,相当于new StudentServiceImpl(),但返回的是Object对象
                Object studentServiceImplInstance = studentServiceImplClass.newInstance();
                //创建StudentAction对象,相当于new StudentAction(),但返回的是Object对象
                Object studentActionInstance = studentActionClass.newInstance();
                
                //使用反射机制调用StudentServiceImpl的setStudentDao方法,参数是StudentDaoImpl对象,
                //第一个参数是执行方法的类实例,第二个参数是方法参数
                setDaoMethod.invoke(studentServiceImplInstance, studentDaoImplnstance);
                setServiceMethod.invoke(studentActionInstance, studentServiceImplInstance);
                //调用StudentAction的printName方法
                ((StudentAction)studentActionInstance).printName();
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    复制代码

    测试结果:

  • 相关阅读:
    sql server 2008数据库 降为 sql server 2005数据库 最终方案总结
    android 单元测试
    C# 5.0中引入了async 和 await
    Android之NDK开发
    Java NIO原理 图文分析及代码实现
    【第六篇】Volley之https相关
    【第五篇】Volley代码修改之图片二级缓存以及相关源码阅读(重写ImageLoader.ImageCache)
    【第四篇】Volley修改之GsonRequest
    java复习 --集合类
    android 图片加载优化,避免oom问题产生
  • 原文地址:https://www.cnblogs.com/yangjingru/p/12129264.html
Copyright © 2011-2022 走看看