一、IoC(Inverse of Control)
简介
1.IoC是一种设计思想,将程序中原本手动创建对象的控制权交给Spring框架管理。
2.IoC容器是实现IOC的载体实际上是一个map(key, value),存放各种对象。IoC容器像一个工厂,当需要创建对象的时候,只需要配置配置文件/注解,不需要考虑对象的具体创建过程。
3.控制反转采用的方法是依赖注入(Dependency Injection)
IoC的初始化过程
- Resource定位
- -ClassPathXmlApplicationContext:从类的根路径下加载配置文件
- FileSystemXmlApplicationContext:从磁盘路径下加载配置文件
- BeanDefinition的载入
- 向IoC容器中注册BeanDefinition
- 通过一个HashMap持有载入的 BeanDefinition
refresh()方法标志着IoC容器的正式启动
如何从IoC容器中获取beans
1.使用ApplicationContext接口
ApplicationContext实现了BeanFactory接口,是预加载,每个bean都在ApplicationContext启动之后实例化。
- 实现了ApplicationContext接口的工厂,就可以获取容器中的Bean对象了。
ApplicationContext接口常用实现类
- ClassPathXmlApplicationContext:从类的根路径下加载配置文件
- FileSystemXmlApplicationContext:从磁盘路径下加载配置文件
- AnnotationConfigApplicationContext:使用注解配置时,用这个类创建spring容器,读取注解。
2.使用BeanFactory接口
使用懒加载的方式,只有在getBean()方法调用beans的时候才实例化。
二、AOP(Aspect-Oriented Programming)
AOP面向切面编程,将与业务无关却为业务模块共同调用的逻辑功能封装起来,便于减少系统的重复代码,降低模块间耦合度,有利于拓展及维护。
- AOP基于动态代理,如果要代理的对象,实现InvocationHandler 接口,那么Spring AOP会用JDK Proxy创建代理对象。
- 对于没有实现接现的对象,Spring AOP会用Cglib ,生成一个被代理对象的
子类来作为代理。
三、动态代理是什么?
当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。**这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
动态代理的应用:
Spring的AOP
加事务
加权限
加日志
三、怎么实现动态代理?
在不修改已有代码的前提下,完成增强功能。不写代理类,直接得到代理Class对象,然后创建代理实例。代理类和目标类应实现同一组接口,调用Proxy的newProxyInstance方法可以生成代理对象。
实现一个ProxyHandler类,该类用来创建代理对象,这个类调用Proxy的newProxyInstance方法可以生成代理对象。newProxyInstance有三个参数如下。这个ProxyHandler类实现了InvocationHandler接口,重写了invoke,增强代码就写在invoke方法里。(InvocationHandler接口只有一个invoke方法):
public class ProxyHandler implements InvocationHandler {
private Object targetObject;//被代理的对象
//获得被代理对象的类加载器和实现接口作为Proxy.newProxyInstance方法的参数
public Object newProxyInstance(Object targetObject){
this.targetObject = targetObject;
//targetObject.getClass().getClassLoader():被代理对象的类加载器
//targetObject.getClass().getInterfaces():被代理对象的实现接口
//this 代理对象,该对象实现了InvocationHandler接口所以有invoke方法,通过invoke方法可以调用被代理对象的方法,在调用方法时会调用它的invoke方法。
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
//该方法在代理对象调用方法时调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在这里可以通过判断方法名来决定执行什么功能
System.out.println("记录日志");
return method.invoke(targetObject,args); //调用被代理对象的方法
}
}