注意:
IOC和AOP不是spring框架提出来的,在spring框架之前就已经有了,只不过更偏向于理论化,spring在技术层面上把这两个思想做了非常好的实现(Java
)
1.什么是IOC?
IoC Inversion of Control
(控制反转/反转控制) 注意他是一个思想,不是一个技术实现
描述的事情
:Java开发领域对象的创建、管理问题
传统的开发方式
:比如类A依赖于类B,往往会在类A中new一个类B的对象
IOC思想下的开发方式
:我们不用自己去new对象了,而是由Ioc容器(Spring框架)去帮助我们实例化对象并且管理它,我们需要使用到哪个对象,就去问IoC容器要即可,这样看起来我们丧失了一个权力(创建、管理对象的权力),但是得到了一个福利,那就是不用考虑对象的创建、管理等一系列事情
为什么叫做控制反转?
控制: 指的是对象的创建(实例化、管理)的权力
反转: 控制权交给了外部环境了(Spring框架,Ioc容器)
Ioc解决了什么问题
Ioc和DI的区别?
DI: 依赖注入
IOC和DI描述的是同一件事情,只不过角度不一样罢了
下面以一个转账案例来说明:
2.Ioc实现:
==2.==什么是AOP
AOP:Aspect oriented Programming面向切面编程/面向方面编程
Aop是oop的延续,从OOP说起
OOP三大特征:封装、继承和多态
oop是一种垂直继承体系
oop编程思想可以解决大多数代码重复问题,但是有一些情况是处理不了的,比如下面的在顶级父类Animal中的多个方法中相同位置出现了重复代码,OOP就解决不了
横切逻辑代码:假设我们在所有的方法执行前都要打印相同的一段话,那就意味着我们需要在每个方法最顶层添加上sout("打印一段话")
横切逻辑代码存在什么问题:
AOP出场,AOP独辟蹊径提出横向抽取机制,将横向逻辑代码和业务代码分开
代码拆分容易,那摩如何在不改变原有业务逻辑的情况下,悄无声息的把横切逻辑代码应用到原有的业务逻辑中,达到和原来一样的效果,这个是比较难的
AOP在解决什么问题?
在不改变原有业务逻辑情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复
为什么叫做面向切面编程
切
: 指的是横切逻辑,原有业务逻辑代码我们不能动,只能操作横切逻辑代码,所以面向横切逻辑
面
:横切逻辑代码往往要影响很多个方法,每一个方法都如同一个点,多个点构成一个面,有一个面的概念在里面
AOP的底层实现原理就是基于动态代理的,下面来通过代码来实现动态代理:再次之前先要知道啥是静态代理,请看静态代理模式
1.抽象出一个公共的接口,表示实例对象和代理对象都要做的事情
/**
* 接口,租房
* jdk动态代理,
* cglib代理(需要开发者导入jar包)
*/
public interface IRentingHouse {
void rentHouse();
}
2.委托对象,也就是实例对象想要做的事
/**
* 委托方(委托对象)
*/
public class RentingHouseImpl implements IRentingHouse {
@Override
public void rentHouse() {
System.out.println("我要租用一室一厅的房子");
}
}
3.代理对象,也就是代理真实对象去干真实对象想做的事情
package aop.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy {
public static void main(String[] args) {
// 委托方,委托对象
IRentingHouse rentingHouse = new RentingHouseImpl();
// 获取代理对象
IRentingHouse proxy =(IRentingHouse) Proxy.newProxyInstance(rentingHouse.getClass().getClassLoader(), rentingHouse.getClass().getInterfaces(),
new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 实例对象要调用的方法
* @param args 实例对象要调用方法需要传递的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 写增强逻辑
System.out.println("中介 (代理) 收取服务费3000元");
// 调用原有业务逻辑
result = method.invoke(rentingHouse, args);
System.out.println("客户信息卖了3毛钱");
return result;
}
});
proxy.rentHouse();
}
}
4.启动main方法测试即可
5.优化,将该代理对象的生成封装成工厂方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理对象工厂:生成代理对象的
*/
public class ProxyFactory {
private ProxyFactory(){
}
private static ProxyFactory proxyFactory = new ProxyFactory();
public static ProxyFactory getInstance(){
return proxyFactory;
}
/**
* JDK动态代理
* @param obj 委托对象
* @return 代理对象
*/
public Object getJDKProxy(Object obj){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 写增强逻辑
System.out.println("中介 (代理) 收取服务费3000元");
// 调用原有业务逻辑
result = method.invoke(obj, args);
System.out.println("客户信息卖了3毛钱");
return result;
}
});
}
}
6.启动测试
public class JdkProxyTest {
public static void main(String[] args) {
IRentingHouse rentingHouse = new RentingHouseImpl(); // 委托对象--委托方
// 从代理对象工厂获取代理对象
IRentingHouse jdkProxy =(IRentingHouse) ProxyFactory.getInstance().getJDKProxy(rentingHouse);
jdkProxy.rentHouse();
}
}
基于cglib实现的动态代理
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1.2</version>
<dependency>