• Spring IOC、DI、AOP原理和实现


    (1)Spring IOC原理

             IOC的意思是控件反转也就是由容器控制程序之间的关系,把控件权交给了外部容器,之前的写法,由程序代码直接操控,而现在控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。网上有一个很形象的比喻:

    我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,
    投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,
    就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
      那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,
    告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,
    我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的
    机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,
    把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,
    而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
    
     (2)DI(Dependency Injection,依赖注入)
    
            IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,
    依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 
    spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。
    在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系
    的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。
    
    
    下面来模拟下IOC和DI的实现原理。
    项目的结构图如下:
    1、首先定义DAO接口和接口的实现类
    
    1. package com.dao;  
    2.   
    3. public interface PersonDAO {  
    4.     public void save();  
    5. }  
    1. package com.dao.impl;  
    2.   
    3. import com.dao.PersonDAO;  
    4.   
    5. public class PersonDaoImpl implements PersonDAO {  
    6.   
    7.     @Override  
    8.     public void save() {  
    9.         System.out.println("保存");  
    10.     }  
    11.   
    12. }  
    2、创建一个Junit测试类
    1. package com.test;  
    2.   
    3. import org.junit.Test;  
    4. import org.springframework.context.ApplicationContext;  
    5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
    6.   
    7. import com.dao.PersonDAO;  
    8. import com.myUtil.MyClassPathXmlApplicationContext;  
    9. import com.service.PersonService;  
    10.   
    11.   
    12. public class PersonTest {  
    13.       
    14.     @Test  
    15.     public void instanceSpring1(){  
    16.         /** 
    17.          *  
    18.          * spring 的实现 
    19.          */  
    20.         //IOC  
    21.         ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");  
    22.         PersonDAO pd = (PersonDAO) ac.getBean("personDAO");  
    23.         pd.save();  
    24.         //DI  
    25.         PersonService ps = (PersonService) ac.getBean("personService");  
    26.         ps.save();  
    27.     }  
    28.       
    29.     @Test  
    30.     public void instanceSpring2(){  
    31.           
    32.         /** 
    33.          * 我的实现 
    34.          *  
    35.          */  
    36.         MyClassPathXmlApplicationContext mac = new MyClassPathXmlApplicationContext("beans.xml");  
    37.         PersonDAO mpd = (PersonDAO) mac.getBean("personDAO");  
    38.         mpd.save();  
    39.         //DI  
    40.         PersonService ps = (PersonService) mac.getBean("personService");  
    41.         ps.save();  
    42.     }  
    43.       
    44. }  
    方法instanceSpring1为Spring中的实现用到ClassPathXmlApplicationContext类,要实现IOC的原理要定义自己 的MyClassPathXmlApplicationContext首先读出beans.xml中的配置信息,通过反射机制实现bean,最后注入所需要的 bean。
    1. package com.myUtil;  
    2. import java.beans.Introspector;  
    3. import java.beans.PropertyDescriptor;  
    4. import java.lang.reflect.Method;  
    5. import java.net.URL;  
    6. import java.util.ArrayList;  
    7. import java.util.HashMap;  
    8. import java.util.List;  
    9. import java.util.Map;  
    10. import org.dom4j.Document;  
    11. import org.dom4j.Element;  
    12. import org.dom4j.io.SAXReader;  
    13.   
    14. public class MyClassPathXmlApplicationContext {  
    15.     // xml所有的属性  
    16.     private ArrayList<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();  
    17.     // xml中所有的bean  
    18.     private Map<String, Object> sigletons = new HashMap<String, Object>();  
    19.   
    20.     public MyClassPathXmlApplicationContext(String file) {  
    21.         readXml(file);  
    22.         instanceBeans();  
    23.         instanceObject();  
    24.     }  
    25.   
    26.     /** 
    27.      * 注入 
    28.      */  
    29.     private void instanceObject() {  
    30.         for (BeanDefinition beanDefinition : beanDefinitions) {  
    31.             //判断有没有注入属性  
    32.             if (beanDefinition.getProperty() != null) {  
    33.                 Object bean = sigletons.get(beanDefinition.getId());  
    34.                 if (bean != null) {  
    35.                     try {  
    36.                         //得到被注入bean的所有的属性  
    37.                         PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();  
    38.                         //得到所有的注入bean属性  
    39.                         for(PropertyDefinition propertyDefinition:beanDefinition.getProperty()){  
    40.                             for(PropertyDescriptor propertyDescriptor:ps){  
    41.                                 if(propertyDescriptor.getName().equals(propertyDefinition.getName())){  
    42.                                     Method setter = propertyDescriptor.getWriteMethod();//获取set方法  
    43.                                     if(setter!=null){  
    44.                                         setter.setAccessible(true);//得到private权限  
    45.                                         //注入属性  
    46.                                         setter.invoke(bean, sigletons.get(propertyDefinition.getRef()));  
    47.                                     }  
    48.                                     break;  
    49.                                 }  
    50.                             }  
    51.                         }  
    52.                     } catch (Exception e) {  
    53.                         // TODO Auto-generated catch block  
    54.                         e.printStackTrace();  
    55.                     }  
    56.                 }  
    57.             }  
    58.         }  
    59.     }  
    60.   
    61.     /** 
    62.      * 实例所有的bean 
    63.      */  
    64.     private void instanceBeans() {  
    65.         for (int i = 0; i < beanDefinitions.size(); i++) {  
    66.             BeanDefinition bd = beanDefinitions.get(i);  
    67.             try {  
    68.                 try {  
    69.                     if (bd.getClassName() != null  
    70.                             && !bd.getClassName().equals(""))  
    71.                         sigletons.put(bd.getId(), Class.forName(  
    72.                                 bd.getClassName()).newInstance());  
    73.                 } catch (InstantiationException e) {  
    74.                     // TODO Auto-generated catch block  
    75.                     e.printStackTrace();  
    76.                 } catch (IllegalAccessException e) {  
    77.                     // TODO Auto-generated catch block  
    78.                     e.printStackTrace();  
    79.                 }  
    80.             } catch (ClassNotFoundException e) {  
    81.                 // TODO Auto-generated catch block  
    82.                 e.printStackTrace();  
    83.             }  
    84.         }  
    85.     }  
    86.   
    87.     /** 
    88.      * 读xml 
    89.      *  
    90.      * @param file 
    91.      */  
    92.     private void readXml(String file) {  
    93.         try {  
    94.             SAXReader reader = new SAXReader(); // 使用SAX方式解析XML  
    95.             URL xmlPath = this.getClass().getClassLoader().getResource(file);  
    96.             Document doc = reader.read(xmlPath);  
    97.             Element root = doc.getRootElement(); // 取得根节点  
    98.             List<Element> beans = root.elements();  
    99.             for (Element element : beans) {  
    100.                 String id = element.attributeValue("id");// id;  
    101.                 String clazz = element.attributeValue("class");  
    102.                 BeanDefinition bd = new BeanDefinition(id, clazz);  
    103.                 // 读取子元素  
    104.                 if (element.hasContent()) {  
    105.                     List<Element> propertys = element.elements();  
    106.                     for (Element property : propertys) {  
    107.                         String name = property.attributeValue("name");  
    108.                         String ref = property.attributeValue("ref");  
    109.                         PropertyDefinition pd = new PropertyDefinition(name,  
    110.                                 ref);  
    111.                         bd.getProperty().add(pd);  
    112.                     }  
    113.                 }  
    114.                 beanDefinitions.add(bd);  
    115.             }  
    116.         } catch (Exception e) {  
    117.             // TODO: handle exception  
    118.         }  
    119.     }  
    120.   
    121.     /** 
    122.      * 通过名字得到bean 
    123.      *  
    124.      * @param str 
    125.      * @return 
    126.      */  
    127.     public Object getBean(String str) {  
    128.         return sigletons.get(str);  
    129.     }  
    130.   
    131. }  
    读取所的bean实体
    1. package com.myUtil;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. public class BeanDefinition {  
    7.     private String id;  
    8.     private String className;  
    9.     private List<PropertyDefinition> property = new ArrayList<PropertyDefinition>();  
    10.   
    11.     public BeanDefinition(String id, String className) {  
    12.         super();  
    13.         this.id = id;  
    14.         this.className = className;  
    15.     }  
    16.   
    17.     public String getId() {  
    18.         return id;  
    19.     }  
    20.   
    21.     public void setId(String id) {  
    22.         this.id = id;  
    23.     }  
    24.   
    25.     public String getClassName() {  
    26.         return className;  
    27.     }  
    28.   
    29.     public void setClassName(String className) {  
    30.         this.className = className;  
    31.     }  
    32.   
    33.     public List<PropertyDefinition> getProperty() {  
    34.         return property;  
    35.     }  
    36.   
    37.     public void setProperty(List<PropertyDefinition> property) {  
    38.         this.property = property;  
    39.     }  
    40.   
    41. }  
    注入属性实体
    1. package com.myUtil;  
    2.   
    3. public class PropertyDefinition {  
    4.     private String name;  
    5.     private String ref;  
    6.   
    7.     public PropertyDefinition(String name, String ref) {  
    8.         this.name = name;  
    9.         this.ref = ref;  
    10.     }  
    11.   
    12.     public String getName() {  
    13.         return name;  
    14.     }  
    15.   
    16.     public void setName(String name) {  
    17.         this.name = name;  
    18.     }  
    19.   
    20.     public String getRef() {  
    21.         return ref;  
    22.     }  
    23.   
    24.     public void setRef(String ref) {  
    25.         this.ref = ref;  
    26.     }  
    27.   
    28. }  
    业务接口和实现类
    1. package com.service;  
    2.   
    3. public interface PersonService {  
    4.     public void save();  
    5. }  
    1. package com.service.impl;  
    2.   
    3. import com.dao.PersonDAO;  
    4. import com.service.PersonService;  
    5.   
    6. public class PersonServiceImpl implements PersonService{  
    7.     private PersonDAO pdo;  
    8.   
    9.     public PersonDAO getPdo() {  
    10.         return pdo;  
    11.     }  
    12.   
    13.     public void setPdo(PersonDAO pdo) {  
    14.         this.pdo = pdo;  
    15.     }  
    16.   
    17.     @Override  
    18.     public void save() {  
    19.         pdo.save();  
    20.     }  
    21.       
    22. }  
    beans.xml配置
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
    4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
    5.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
    6.             
    7.     <bean id="personDAO" class="com.dao.impl.PersonDaoImpl"></bean>  
    8.     <bean id="personService" class="com.service.impl.PersonServiceImpl">  
    9.         <property name="pdo" ref="personDAO"></property>  
    10.     </bean>  
    11. </beans>  
    
    

    (3)AOP面向切面

        AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向切面编程。要理解AOP首先得弄明白代理的概念。对于代理看下点击打开链接这篇文章。

      AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。 AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中"临时"生成 AOP 动态代理类,因此也被称为运行时增强。

    知道这些其他的就是些配置了。

    简单的实现annotations和xml对AOP的实现。

    首先看下目录结构

    MyInterceptor、MyInterceptor2分别是以annotations和xml定义的切面类

    [java] view plaincopy
    1. package com.service;  
    2.   
    3. import org.aspectj.lang.annotation.Aspect;  
    4. import org.aspectj.lang.annotation.Before;  
    5. import org.aspectj.lang.annotation.Pointcut;  
    6.   
    7. @Aspect  
    8. public class MyInterceptor {  
    9.     @Pointcut("execution (* com.serviceImpl.PersonServiceImpl.*(..))")  
    10.     private void myMethod(){};  
    11.       
    12.     @Before("myMethod()")  
    13.     public void doAccessCheck(){  
    14.         System.out.println("before");  
    15.     }  
    16.       
    17. }  

    [java] view plaincopy
    1. package com.service;  
    2.   
    3. public class MyInterceptor2 {  
    4.     public void doAccessCheck(){  
    5.         System.out.println("before");  
    6.     }  
    7. }  

    业务和接口

    [java] view plaincopy
    1. package com.service;  
    2.   
    3. public interface PersonService {  
    4.     public void save(String name);  
    5.     public void update(String name);  
    6. }  

    [java] view plaincopy
    1. package com.serviceImpl;  
    2.   
    3. import com.service.PersonService;  
    4.   
    5. public class PersonServiceImpl implements PersonService {  
    6.   
    7.     @Override  
    8.     public void save(String name) {  
    9.         // TODO Auto-generated method stub  
    10.         System.out.println("保存");  
    11.     }  
    12.   
    13.     @Override  
    14.     public void update(String name) {  
    15.         // TODO Auto-generated method stub  
    16.         System.out.println("修改");  
    17.     }  
    18.   
    19. }  

    简单做个方法前通知,其他的都一样。

    [java] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
    5.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
    6.             http://www.springframework.org/schema/aop  
    7.            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
    8.   
    9.     <aop:aspectj-autoproxy/>  
    10.       
    11.     <bean id="personServiceImpl" class="com.serviceImpl.PersonServiceImpl"></bean>  
    12.     <bean id="personInterceptor" class="com.service.MyInterceptor2"></bean>  
    13.       
    14.     <aop:config>  
    15.         <aop:aspect id="asp" ref="personInterceptor">  
    16.             <aop:pointcut id="myCut" expression="execution (* com.serviceImpl.PersonServiceImpl.*(..))"/>  
    17.             <aop:before pointcut-ref="myCut" method="doAccessCheck"/>  
    18.         </aop:aspect>       
    19.     </aop:config>  
    20. </beans>  

    测试类

    [java] view plaincopy
    1. package com.test;  
    2.   
    3.   
    4.   
    5. import org.junit.Test;  
    6. import org.springframework.context.ApplicationContext;  
    7. import org.springframework.context.support.ClassPathXmlApplicationContext;  
    8.   
    9. import com.service.PersonService;  
    10.   
    11. public class AopTest {  
    12.       
    13.     @Test  
    14.     public void interceptorTest(){  
    15.         ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");  
    16.         PersonService ps = (PersonService) ac.getBean("personServiceImpl");  
    17.         ps.save("aa");  
    18.     }  
    19. }  

  • 相关阅读:
    DC综合流程
    DC set_tcl脚本配置
    同步FIFO设计
    顺序脉冲 发生器
    状态机的写法
    verilog串并转换
    indexOf()
    jQuery 效果
    jQuery 事件
    jQuery css
  • 原文地址:https://www.cnblogs.com/daichangya/p/12958790.html
Copyright © 2020-2023  润新知