(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. public interface PersonDAO {
  3. public void save();
  4. }
  1. package com.dao.impl;
  2. import com.dao.PersonDAO;
  3. public class PersonDaoImpl implements PersonDAO {
  4. @Override
  5. public void save() {
  6. System.out.println("保存");
  7. }
  8. }
2、创建一个Junit测试类
  1. package com.test;
  2. import org.junit.Test;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import com.dao.PersonDAO;
  6. import com.myUtil.MyClassPathXmlApplicationContext;
  7. import com.service.PersonService;
  8. public class PersonTest {
  9. @Test
  10. public void instanceSpring1(){
  11. /**
  12. *
  13. * spring 的实现
  14. */
  15. //IOC
  16. ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
  17. PersonDAO pd = (PersonDAO) ac.getBean("personDAO");
  18. pd.save();
  19. //DI
  20. PersonService ps = (PersonService) ac.getBean("personService");
  21. ps.save();
  22. }
  23. @Test
  24. public void instanceSpring2(){
  25. /**
  26. * 我的实现
  27. *
  28. */
  29. MyClassPathXmlApplicationContext mac = new MyClassPathXmlApplicationContext("beans.xml");
  30. PersonDAO mpd = (PersonDAO) mac.getBean("personDAO");
  31. mpd.save();
  32. //DI
  33. PersonService ps = (PersonService) mac.getBean("personService");
  34. ps.save();
  35. }
  36. }
方法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. public class MyClassPathXmlApplicationContext {
  14. // xml所有的属性
  15. private ArrayList<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
  16. // xml中所有的bean
  17. private Map<String, Object> sigletons = new HashMap<String, Object>();
  18. public MyClassPathXmlApplicationContext(String file) {
  19. readXml(file);
  20. instanceBeans();
  21. instanceObject();
  22. }
  23. /**
  24. * 注入
  25. */
  26. private void instanceObject() {
  27. for (BeanDefinition beanDefinition : beanDefinitions) {
  28. //判断有没有注入属性
  29. if (beanDefinition.getProperty() != null) {
  30. Object bean = sigletons.get(beanDefinition.getId());
  31. if (bean != null) {
  32. try {
  33. //得到被注入bean的所有的属性
  34. PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
  35. //得到所有的注入bean属性
  36. for(PropertyDefinition propertyDefinition:beanDefinition.getProperty()){
  37. for(PropertyDescriptor propertyDescriptor:ps){
  38. if(propertyDescriptor.getName().equals(propertyDefinition.getName())){
  39. Method setter = propertyDescriptor.getWriteMethod();//获取set方法
  40. if(setter!=null){
  41. setter.setAccessible(true);//得到private权限
  42. //注入属性
  43. setter.invoke(bean, sigletons.get(propertyDefinition.getRef()));
  44. }
  45. break;
  46. }
  47. }
  48. }
  49. } catch (Exception e) {
  50. // TODO Auto-generated catch block
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. }
  56. }
  57. /**
  58. * 实例所有的bean
  59. */
  60. private void instanceBeans() {
  61. for (int i = 0; i < beanDefinitions.size(); i++) {
  62. BeanDefinition bd = beanDefinitions.get(i);
  63. try {
  64. try {
  65. if (bd.getClassName() != null
  66. && !bd.getClassName().equals(""))
  67. sigletons.put(bd.getId(), Class.forName(
  68. bd.getClassName()).newInstance());
  69. } catch (InstantiationException e) {
  70. // TODO Auto-generated catch block
  71. e.printStackTrace();
  72. } catch (IllegalAccessException e) {
  73. // TODO Auto-generated catch block
  74. e.printStackTrace();
  75. }
  76. } catch (ClassNotFoundException e) {
  77. // TODO Auto-generated catch block
  78. e.printStackTrace();
  79. }
  80. }
  81. }
  82. /**
  83. * 读xml
  84. *
  85. * @param file
  86. */
  87. private void readXml(String file) {
  88. try {
  89. SAXReader reader = new SAXReader(); // 使用SAX方式解析XML
  90. URL xmlPath = this.getClass().getClassLoader().getResource(file);
  91. Document doc = reader.read(xmlPath);
  92. Element root = doc.getRootElement(); // 取得根节点
  93. List<Element> beans = root.elements();
  94. for (Element element : beans) {
  95. String id = element.attributeValue("id");// id;
  96. String clazz = element.attributeValue("class");
  97. BeanDefinition bd = new BeanDefinition(id, clazz);
  98. // 读取子元素
  99. if (element.hasContent()) {
  100. List<Element> propertys = element.elements();
  101. for (Element property : propertys) {
  102. String name = property.attributeValue("name");
  103. String ref = property.attributeValue("ref");
  104. PropertyDefinition pd = new PropertyDefinition(name,
  105. ref);
  106. bd.getProperty().add(pd);
  107. }
  108. }
  109. beanDefinitions.add(bd);
  110. }
  111. } catch (Exception e) {
  112. // TODO: handle exception
  113. }
  114. }
  115. /**
  116. * 通过名字得到bean
  117. *
  118. * @param str
  119. * @return
  120. */
  121. public Object getBean(String str) {
  122. return sigletons.get(str);
  123. }
  124. }
读取所的bean实体
  1. package com.myUtil;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class BeanDefinition {
  5. private String id;
  6. private String className;
  7. private List<PropertyDefinition> property = new ArrayList<PropertyDefinition>();
  8. public BeanDefinition(String id, String className) {
  9. super();
  10. this.id = id;
  11. this.className = className;
  12. }
  13. public String getId() {
  14. return id;
  15. }
  16. public void setId(String id) {
  17. this.id = id;
  18. }
  19. public String getClassName() {
  20. return className;
  21. }
  22. public void setClassName(String className) {
  23. this.className = className;
  24. }
  25. public List<PropertyDefinition> getProperty() {
  26. return property;
  27. }
  28. public void setProperty(List<PropertyDefinition> property) {
  29. this.property = property;
  30. }
  31. }
注入属性实体
  1. package com.myUtil;
  2. public class PropertyDefinition {
  3. private String name;
  4. private String ref;
  5. public PropertyDefinition(String name, String ref) {
  6. this.name = name;
  7. this.ref = ref;
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setName(String name) {
  13. this.name = name;
  14. }
  15. public String getRef() {
  16. return ref;
  17. }
  18. public void setRef(String ref) {
  19. this.ref = ref;
  20. }
  21. }
业务接口和实现类
  1. package com.service;
  2. public interface PersonService {
  3. public void save();
  4. }
  1. package com.service.impl;
  2. import com.dao.PersonDAO;
  3. import com.service.PersonService;
  4. public class PersonServiceImpl implements PersonService{
  5. private PersonDAO pdo;
  6. public PersonDAO getPdo() {
  7. return pdo;
  8. }
  9. public void setPdo(PersonDAO pdo) {
  10. this.pdo = pdo;
  11. }
  12. @Override
  13. public void save() {
  14. pdo.save();
  15. }
  16. }
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. <bean id="personDAO" class="com.dao.impl.PersonDaoImpl"></bean>
  7. <bean id="personService" class="com.service.impl.PersonServiceImpl">
  8. <property name="pdo" ref="personDAO"></property>
  9. </bean>
  10. </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
plain
copy

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

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

业务和接口

[java] view
plain
copy

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

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

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

[java] view
plain
copy

  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. <aop:aspectj-autoproxy/>
  9. <bean id="personServiceImpl" class="com.serviceImpl.PersonServiceImpl"></bean>
  10. <bean id="personInterceptor" class="com.service.MyInterceptor2"></bean>
  11. <aop:config>
  12. <aop:aspect id="asp" ref="personInterceptor">
  13. <aop:pointcut id="myCut" expression="execution (* com.serviceImpl.PersonServiceImpl.*(..))"/>
  14. <aop:before pointcut-ref="myCut" method="doAccessCheck"/>
  15. </aop:aspect>
  16. </aop:config>
  17. </beans>

测试类

[java] view
plain
copy

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

Spring IOC、DI、AOP原理和实现的更多相关文章

  1. spring IOC DI AOP MVC 事务, mybatis 源码解读

    demo https://gitee.com/easybao/aop.git spring DI运行时序 AbstractApplicationContext类的 refresh()方法 1: pre ...

  2. Spring+IOC(DI)+AOP概念及优缺点

    Spring pring是一个轻量级的DI和AOP容器框架. 说它轻量级有一大部分原因是相对与EJB的(虽然本人从没有接触过EJB的应用),重要的是,Spring是非侵入式的,基于spring开发的应 ...

  3. 黑马-Spring(IOC&DI) AOP

    IOC(控制翻转) 概念 把对象的创建.初始化.销毁等工作交给spring容器来做 案例 环境 步骤 1.  写一个HelloWorld类 2.  写一个配置文件   把hello类放到spring容 ...

  4. 170511、Spring IOC和AOP 原理彻底搞懂

    Spring提供了很多轻量级应用开发实践的工具集合,这些工具集以接口.抽象类.或工具类的形式存在于Spring中.通过使用这些工具集,可以实现应用程序与各种开源技术及框架间的友好整合.比如有关jdbc ...

  5. Spring IOC DI AOP 的简单理解及应用

    Spring两大特性:IOC 和AOP.IOC 控制反转,AOP 面向切面编程 spring 核心容器的主要组件时Bean工厂(BeanFactory) ,Bean 工厂使用控制反转模式来降低程序代码 ...

  6. coding++:Spring IOC/DI 实现原理

    什么是 SpringIOC: spring ioc 指的是控制反转,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.交由Spring容器统一进行管理,从而实现松耦合. “控制反 ...

  7. spring+IOC+DI+AOP优点分析(一)

    Spring是什么: Spring是一个轻量级的DI和AOP容器框架. 说它轻量级有一大部分原因是相对与EJB的(虽然本人从没有接触过EJB的应用),重要的是,Spring是非侵入式的,基于sprin ...

  8. Spring ioc与aop的理解

    一 spring的特点 1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易 ...

  9. 【转】spring - ioc和aop

    [转]spring - ioc和aop 1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对 ...

  10. J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP

    J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP 前言   搜狐畅游笔试题中有一道问答题涉及到回答谈谈对Spring IOC与AOP的理解.特将相关内容进行整理.    ...

随机推荐

  1. vue serve 部署 步骤说明

    1. 构建镜像 docker build -t 镜像名称:镜像TAG --build-arg URL=http://localhost:8081 --build-arg PORT=2000 --bui ...

  2. airflow 学习

    入门 Get started developing workflows with Apache Airflow Getting started with Apache Airflow  

  3. windows系统使用UnblockNeteaseMusic解锁网易云音乐灰色歌曲

    使用UnblockNeteaseMusic解锁网易云音乐灰色歌曲 一.问题 用网易云音乐听歌曲,有的曲目听不了,如下: 二.解决步骤 参照:https://github.com/nondanee/Un ...

  4. ASP.NET Core – MVC

    前言 在 ASP.NET Core – MVC vs Razor Page 里有提到 MVC. 它算是 WebAPI 的抽象. 但是通常 MVC 指的是比较传统的 Website, WebAPI 则是 ...

  5. DOM – Work with Document.styleSheets and JS/Scss Breakpoint Media Query

    前言 为了方便管理, 我们会定义 CSS Variables, 类似于全局变量. 有时候做特效的时候还需要 JavaScript 配合, 这时就会希望 JavaScript 可以获取到 CSC Var ...

  6. Facebook – Facebook Page Embed

    前言 在网站嵌套 Facebook 专页是很好的推广方式哦. 虽然网站还是需要做 Blog, 但是通常被订阅的都是 Facebook 专页而不是网站 Blog. 开通账号 它的 setup 很简单, ...

  7. Windows 调试工具课程

    本文是我在集团内部上的课程记录而成的博客内容.在本次课程里面将和大家介绍一些在 Windows 上常用的调试工具,以及调查问题的常见套路.适合于伙伴们入门 Windows 调试 本文以下内容是采用原本 ...

  8. 图形化客户端工具——Navicat

    1.下载 下载地址:https://wwb.lanzoub.com/i4TuZ0g3okod   破解:     解压后有两个文件          先点击第一个文件依次安装     安装完成后    ...

  9. @RequestBody注意事项

    使用@RequestBody注解时,是用于接收Content-Type为application/json类型的请求,数据类型是JSON:{"aaa":"111" ...

  10. httpclient调用接口

    有时候会将参数(返回结果)压缩(解压),加密(解密) 将json参数通过GZip压缩 Base64加密 1 public static String gzipAndEncryption(String ...