1 AOP 的作用及优势
作用:
在程序运行期间,不修改源码对已有方法进行增强。
优势:
减少重复代码
提高开发效率
维护方便
2 AOP 的实现方式
使用动态代理技术
简单案列说明: 动态代理基于接口与子类的实现
定义一个接口
package com.qyy.proxy;
/**
* @description: 工人接口类
* @author: Mr.Yang
**/
public interface IWorker {
/*
* @author Mr.Yang
* @Description: 基本工人接口
* @param [money]
* @return void
*/
public void basicAct(Float money);
/*
* @author Mr.Yang
* @Description: 技术工人
* @param [money]
* @return void
*/
public void dangerAct(Float money);
}
-----------------------------------------------------------------------------------------------------
## 定义一个实现类,实现接口
package com.qyy.proxy;
/**
* @description: 模拟一个劳务公司
* @author: Mr.Yang
**/
public class Worker implements IWorker{
/*
* @author Mr.Yang
* @Description: 基本工人
* @param [money]
* @return void
*/
public void basicAct(Float money){
System.out.println("基本工人,拿到" + money+ "开始工作" );
}
/*
* @author Mr.Yang
* @Description: 技术工人
* @param [money]
* @return void
*/
public void dangerAct(Float money){
System.out.println("技术工人,拿到" + money+ "开始工作" );
}
}
-----------------------------------------------------------------------------------------------------
通过main函数进行测试(方法增强)
public class Client {
public static void main(String[] args) {
//早期:直接去家里找
Actor actor = new Actor();
//通过经纪公司来找演员
/**
* 动态代理
* 作用:不修改源码的基础上,对已有方法增强
* 特点:字节码是随用随创建,随用随加载。
* 基于接口的动态代理:
* 提供者:JDK官方
* 要求:被代理对象最少实现一个接口。
* 涉及的类:Proxy
* 涉及的方法:newProxyInstance
* 方法的参数:
* ClassLoader:类加载器。负责加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
* Class[]:字节码数组。代理对象具有的方法。和被代理对象实现相同的接口。
* 如果被代理对象本身是一个接口的话,直接把被代理对象存入字节码数组中。
* xxx.getClass().getInterfaces() || new Class[]{xxx}
* 固定写法。
* InvocationHandler:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。
* 通常情况下可以写成匿名内部类。
* 策略模式:
* 数据已经有了
* 目的明确。
* 达成目标的过程即是策略。
*
*/
IActor proxyActor = (IActor)Proxy.newProxyInstance(actor.getClass().getClassLoader(), actor.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 rtValue = null;
//1.取出当前方法的参数
Float money= (Float) args[0];
//2.判断方法是什么
if("basicAct".equals(method.getName())){
//基本演出:抽取20% 要求一天5000块以上才接
if(money > 5000f){
rtValue = method.invoke(actor,money*0.8f);
}
}
if("dangerAct".equals(method.getName())){
//高危演出:抽取10% 要求一天20000块以上才接
if(money > 20000f){
rtValue = method.invoke(actor,money*0.9f);
}
}
return rtValue;
}
});
proxyActor.basicAct(10000f);
proxyActor.dangerAct(50000f);
------------------------------------------------------------------------------------------------------
打印结果 ;
基本工人,拿到8000.0开始工作
技术工人,拿到45000.0开始工作
=====================================================================================================
动态代理基子类的实现
定义一个子类 :
ackage com.qyy.proxy;
/**
* @description: 模拟一个劳务公司
* @author: Mr.Yang
**/
public class Worker{
/*
* @author Mr.Yang
* @Description: 基本工人
* @param [money]
* @return void
*/
public void basicAct(Float money){
System.out.println("基本工人,拿到" + money+ "开始工作" );
}
/*
* @author Mr.Yang
* @Description: 技术工人
* @param [money]
* @return void
*/
public void dangerAct(Float money){
System.out.println("技术工人,拿到" + money+ "开始工作" );
}
}
通过main函数进行代理测试方法增强()
package com.qyy.cglib;
public class Client {
public static void main(final String[] args) {
l Worker worker = new Worker();
**
* 动态代理
* 作用:不修改源码的基础上,对已有方法增强
* 特点:字节码是随用随创建,随用随加载。
* 基于子类的动态代理:
* 提供者:第三方cglib库
* 要求:被代理对象不能是最终类。不能被final修饰
* 涉及的类:Enhancer
* 涉及的方法:create
* 方法的参数:
* Class:字节码。被代理对象的字节码。固定写法。
* Callback:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。
* 通常情况下可以写成匿名内部类。
* 我们需要使用它的子接口:MethodInterceptor
* 策略模式:
* 数据已经有了
* 目的明确。
* 达成目标的过程即是策略。
*
*/
Worker workerCglib= (Worker )Enhancer.create(actor.getClass(), new MethodInterceptor() {
/**
* 此处提供增强的代码
* 执行被代理对象的任何方法,都会经过该方法。
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前方法所需的参数
* @param methodProxy 当前方法的代理对象
* @return 和被代理对象的方法具有相同的返回值
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object rValue = null;
// 取出被代理对象的参数
Float money = (Float) args[0];
//判断被代理对象的中方法,进行增强
if ("basicAct".equals(method.getName())){
if (money > 800f){
rValue = method.invoke(worker,money*0.8f);
}
}
if ("dangerAct".equals(method.getName())){
if (money>3000f){
rValue = method.invoke(worker,money*0.9f);
}
}
return rValue;
}
});
workerCglib.basicAct(50000f);
workerCglib.dangerAct(50000F);
}
}