Ioc/DI和Aop(2)

1 Spring IOC

IOC控制反转,其实是一种思想,传统的Java se 是通过new 来创建一个对象,是程序主动的创建依赖对象。IOC是指,通过容器的来帮忙创建和注入依赖对象。类与类直接可以松耦合。

实现方式:配置文件,注解

BeanFactory接口是 IOC的具体实现,用来包装 管理 各种bean。

1.Ioc底层原理

(1)xml配置文件
(2)dom4j解析
(3)工厂设计模式
(4)反射
步骤:

第一步:创建类的.xml文件 <bean id="userService" class="....."/>
第二步:创建一个工厂类:使用dom4j解析配置文件+反射

public class UserFactory{
 
public static UserService getUserService(){
 
//使用dom4j解析配置文件
 
//根据id值获得class的属性值
 
String classValue="class属性值"//使用反射来创建class对象
 
Class class=Class.forName(classValue);
 
UserService service=class.newInstatnce();
 
return service;
 
}
 
}  

  

通过IOC,我们如果改掉UserService类,只需更改bean里面的配置属性就行了,降低了类之间的耦合度

spring依赖注入

spring依赖注入有如下几种方式:
①setter方式注入(设值注入)
②构造器方式注入
    Spring支持利用构造器注入参数实例化Bean方式。只要在Spring的配置文件中增加构造器参数constructor-arg
    Spring就会自动的调用有参数的构造器创建bean对象实例, 整个过程无需程序编码只需要配置applicationContext.xml文件即可
③自动装配功能实现属性自动注入
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,autowire可以针对单个bean进行设置,
autowire的方便之处在于减少xml的注入配置。
在xml配置文件中,可以在<bean/>元素中使用autowire属性指定自动装配规则,一共有五种类型值:
 
 
 

2.Ioc和DI的区别:

(1)Ioc:控制反转,把创建对象交给Spring进行配置
(2)DI:依赖注入。组件之间依赖关系由容器在运行期决定,容器动态的将某个依赖关系注入到组件中。向类里面的属性中设置值
(3)二者关系:DI不能单独存在,要在Ioc基础之上来完成操作,即要先创建对象才能注入属性值。
3.循环依赖

递归调用过程中,发现Bean还在创建中(创建中是指new 出来,但是所有属性值均为null,等待init) 就是循环依赖。spring为解决单例的循环依赖问题,使用了三级缓存。bean的获取过程:一级缓存 -> 二级缓存 -> 三级缓存。

一级:用于存放完全初始化好的bean
二级:存放原始的bean对象(尚未填充属性),用于解决循环依赖
三级:存放bean的工厂对象,解决循环依赖
具体过程:

A创建过程中需要B,于是A将自己放入三级缓存里,去实例化B;
B实例化的时候发现需要A,于是B先查一级缓存 没有,查二级缓存 没有,查三级缓存 有。
然后把三级缓存里的A放到二级缓存,并删除三级缓存里的A
B顺利初始化完自己后,将自己放到一级缓存(此时B中的A状态依然是创建中)
然后返回继续创建A,此时B已经结束,直接从一级缓存中拿到B,完成创建,并把自己放入一级缓存。
Spring整合web项目原理

加载Spring核心配置文件 ApplicationContext context=new ClassPathXmlApplicationContext(“bean1.xml”);加载文件要new一个对象,每次访问都要new对象加载配置,效率低
实现思想:把加载配置文件和创建对象过程,在服务器启动时候完成
实现原理:
  a) ServletContext对象
  b) 监听器(ServletContextListener接口)
  c) 具体使用:
    i. 服务器启动时,为每个项目创建一个ServletContext对象
    ii. 使用监听器可以监听到ServletContext在何时创建
    iii. 在监听器的,ServletContextListener接口的contextInitialized()方法方法中加载Spring配置文件(括号1中代码),创建对象。
    iv. 把创建出来的对象放到ServletContext域对象里面(setAttribute方法)
    v. 获取对象时,从ServletContext域对象中得到(getAttribute方法)
Spring AOP

  面向切面思想,扩展功能时不通过源代码,横向抽取机制。Java面向对象的时候,遇到重复代码可以通过抽取方法和抽取类的方式实现。AOP的理念:将分散在各个业务逻辑中相同的代码通过横向切割的方式抽取到一个独立的模块。

1.AOP思想实现技术

  AspectJ的底层技术:静态代理,在编译时增强,编译时性能更好,该代理类增加了业务类。
  Spring AOP:动态代理,在运行期对业务方法进行增强,不会生成新类。
2.AOP底层原理

  AOP框架负责动态地生成AOP代理类,这个代理类的方法由Advice(通知)和回调目标对象的方法组成,并将改对象作为目标对象使用。

  底层使用动态代理方式来增强方法。

Java动态代理:

  jdk动态代理:需要实现某个接口,(AOP 默认使用jdk动态代理):主要就是Proxy 对象 和 invocationHandler接口,通过实现接口定义横切逻辑。并且通过反射机制调用目标类的代码。
  cglib动态代理:目标类的子类。:底层采用字节码技术,为一个类创建子类,并在子类中拦截父类的方法,织入横切逻辑。final private 的方法不能被重写。
  具体分两种情况:

  (1)有接口的情况:创建接口的实现类的代理对象,jdk动态代理

  (2)没有接口的情况:创建User类的子类的代理对象,cglib动态代理。子类可以通过super调用父类方法

增强:before,after,(前置,后置,异常,最终,环绕增强)

  pointCut:切点 那些范围内的类,接口被当成切点,捕获链接点的结构。

  Advice:通知,定义AOP核实被调用,可以理解为通知,比如 before ,after,around,after-returning,after-throwing

  JoinPoint:连接点,程序执行的一个精确的执行点,比如类中的一个方法,是一个抽象概念。

  Aspect:切面,切点和通知结合起来就是切面,代表对象间的横向关系。

3.JDK动态代理和cglib动态代理

  jdk动态代理:利用反射机制实现代理接口的匿名类,在调业务方法会调用invocationHandler来处理,代理类必须实现invocationHandler接口,重写invoke方法。jdk代理只能代理实现接口的类。
  cglib:对目标类产生一个代理子类,通过方法拦截技术过滤父类的方法调用。代理子类要实现MethodInterceptor接口,不能代理final类型的方法和类;
性能:cglib底层采用字节码技术生成代理类,jdk采用反射机制实现代理,但是随着jdk版本提升jdk代理效率也提升。

4.AOP具体实现

  https://www.jianshu.com/p/520356fc6985

原文链接:https://blog.csdn.net/u012813201/java/article/details/77074795

原文地址:https://www.cnblogs.com/personsiglewine/p/12920440.html