一,什么是spring
spring是一款full-stack轻量级的开源框架,他是以Ioc和aop为核心。
那么问题来了,什么是IOC呢?
IOC称为控制反转,我们以前创建类的时候都是使用new的方式创建的,我们称为主动获取或者说控制正转,而我们的IOC控制反转呢,他就特殊了,是由我们的工厂创建放入容器 中,,当我们使用对象时,工厂就会提供给我们,是被动地接收的。
那么我们来说一下什么是工厂呢?
在这里所说的是工厂模式,工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替 new 操作的一种模式。工厂模式在 Java 程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的 new,我们经常要根据类 Class 生成实例对象,工厂模式也是用来创建实例对象的,工厂模式在后期会给你系统带来更大的可扩展性和尽量少的修改量,提升可扩展性和可维护性。
那么我们来说一下什么是AOP?
面向切面编程。通过预编译方式和运行期动 态代理实现程序功能的统一维护的一种技术。简单来说,aop 是面向切面编程,是使用动态代理技术,实现在不修改 java 源代码的情 况下,运行时实现方法功能的增强。减少重复代码提高开发效率,统一管理调用,便于维护,
AOP的实现原理:在spring 中,框架会根据目标类是否实现了接口来决定采用哪种代理的方式。如果目标对象实现接口,使用的就是jdk动态代理,如果目标对象没有实现接口那么就是使用cglib动态代理。
问题又来了,什么是jdk动态代理,cglib动态代理又是什么呢?
动态代理:
代理类在程序中运行时创建的代理方式被称为动态代理。
jdk动态代理有以下几个特点:
代理对象,需要实现接口
代理对象的生成,是利用jdk的api,在内存中动态生成的对象
jdk代理类所在的包是:java.lang.reflect.Proxy,只需要使用newProxyInstance方法,不过有三个参数
static Object newProxyInstance(ClassLoader loader, Class<?>[]
interfaces,InvocationHandler h )
注意该方法是在 Proxy 类中是静态方法,且接收的三个参数依次为:
ClassLoader loader,:
指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,:
目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:
事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的
方法作为参数传入。
演示
// 对目标对象生成代理对象
IStar proxy = (IStar)Proxy.newProxyInstance(
//1. 类加载器
App.class.getClassLoader(),
//2. 目标对象实现的接口
target.getClass().getInterfaces(),
//3. 事件处理程序
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
// 获取方法参数
Double money = (Double) args[0];
// 判断
if (money > 100000){
// 调用目标对象方法并返回
return method.invoke(target,args);
} else {
System.out.println("忙,没有档期!!!!");
}
return null;
}
}
);
// 生成的代理对象 class com.sun.proxy.$Proxy0 implements IStar
// IStar proxy = (IStar)$Proxy0;
// LiuDeHua proxy = (LiuDeHua)$Proxy0; // 报错:因为只能通过接口的引用接
收具体的实现。
System.out.println(proxy.getClass());
// 调用代理方法
proxy.act(100001d);
proxy.act(1d);
Cglib代理
Cglib 代理,也叫作子类代理,它是在内存中动态构建一个子类对象从而实现对目标对 象功能的扩展. Cglib 是一个强大的高性能代码生成包,它可以在运行期扩展 java 类与实现 java 接 口.它广泛的被许多 AOP 的框架使用,例如 Spring AOP 和 synaop,为他们提供方法的 interception(拦截)
cglib的使用
// 对目标对象创建代理对象, 使用 cglib 代理
LiuDeHuaStar proxy = (LiuDeHuaStar)Enhancer.create(
LiuDeHuaStar.class,
new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method,
Object[] args, MethodProxy methodProxy) throws Throwable {
// 获取方法名称
String methodName = method.getName();
// 获取方法参数
double money = (double) args[0];
// 方法返回值
Object reValue = null;
// 判断
if ("singing".equals(methodName)){
// 判断
if (money > 100000) {
// 调用唱歌方法
reValue = method.invoke(liudehua,args);
}else{
System.out.println("忙,没空开演唱会!");
}
}
else if ("act".equals(methodName)) {
if (money > 1000000) {
// 调用目标对象
reValue = method.invoke(liudehua,args);
} else {
System.out.println("忙,不接新戏!");
}
}
return reValue;
}
});
System.out.println(proxy.getClass());
// 调用代理方法
proxy.singing(1);
proxy.act(2000000);
代理的类不能为 final,否则报错 目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外 的业务方法.
AOP的专业术语
Pointcut(切入点): 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
Advice(通知/增强): 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。 通知的类型: 前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象): 被代理的对象。比如动态代理案例中的演员。
Weaving(织入): 织入指的是把增强用于目标对象,创建代理对象的过程。spring 采用动态代理织入,AspectJ 采用编译 期织入和类装载期织入。
Proxy(代理): 一个类被 AOP 织入增强后,即产生一个结果代理类。比如动态代理案例中的经纪人。
Aspect(切面): 切面指的是切入点和通知的结合。