简述:
Aspect Oriented Programming面向切片编程aop
需求目标:
1.在某个项目中你已经写好了一部分代码,现在想要给这一部分代码添加一个新的附加的功能,并且屏蔽原来代码中不想被调用的代码,总结起来就是中间隔离-开闭原则
思考一下,为了满足这个要求我们新建一个类用这个类继承原来的接口,我们称这个类为代理类,我们用这个代理类去重写接口的方法,并在方法中调用真实类的方法
吃饭接口:
public interfaceEat {
voideatSomth();
}
原始的吃早餐类:
public classEatBreckfastimplementsEat{
staticString*TAG*=EatBreckfast.class.getSimpleName();
@Override
public voideatSomth() {
Log.*e*(*TAG*,"native eat method");
}
}
代理类
public classConstantProxyimplementsEat {
staticString*TAG*=ConstantProxy.class.getSimpleName();
EatBreckfasteatBreckfast;
publicConstantProxy(EatBreckfast eatBreckfast) {
this.eatBreckfast= eatBreckfast;
}
@Override
public voideatSomth() {
*/***
* 调用前想执行的动作
*/Log.*e*(*TAG*,"eat begin");
eatBreckfast.eatSomth();
*/***
* 调用后想执行的动作
*/}
}
其实这个就是所谓静态代理,
但是这样做的弊端是很明显的,由于代理类和真实类是一一对应的那么有多少个真实类我们就要创建多少个代理类,这样就感觉逻辑混乱,然后会多很多的类,
所以我们需要动态代理
动态代理,基础的可以使用Java的jdk的动态代理,jdk动态代理的核心是反射真实类的需要代理的方法。
public classDynamicProxyimplementsInvocationHandler {
staticString*TAG*=DynamicProxy.class.getSimpleName();
privateObjecttarget;
publicDynamicProxy(Object target) {
this.target= target;
}
*/***
*
* 系统类的方法
* 类初始化的时候
* 被系统自动调用
****@param****proxy*
****@param****method*
****@param****args*
****@return*********@throws****Throwable*
*/@Override
publicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable {
*/***
*
* 调用前想执行的动作
*/Log.*e*(*TAG*,"eat begin");
Object result=method.invoke(target,args);
*/***
* 调用后想执行的动作
*/Log.*e*(*TAG*,"eat over");
returnresult;
}
publicTgetProxy(){
return(T) Proxy.*newProxyInstance*(target.getClass().getClassLoader()
,target.getClass().getInterfaces()
,this);
}
}
借助jdk的InvocationHandler接口, 我们可以往原始的方法中添加我们需要的操作,通过动态代理方式我们只需要写将需要代理的操作写到代理类的invoke方法中,这样我们只需要将任意的被代理类(真实类)的对象传入代理类中就可以完成这个对真实类的动态代理调用
调用方式:
DynamicProxy dynamicProxyEat=newDynamicProxy(newEatBreckfast());
Eat eat=(Eat) dynamicProxyEat.getProxy();
eat.eatSomth();
DynamicProxy dynamicProxyDrink=newDynamicProxy(newDrinkWater());
Drink drink=(Drink) dynamicProxyDrink.getProxy();
drink.drinkSomth();
结果打印:
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: eat begin
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: native eat somth
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: eat over
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: eat begin
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: native dink somth
09-06 02:11:57.765 5778-5778/? E/DynamicProxy: eat over
这样我们对于不同的对象欲实现同一功能的代理只需用动态代理类包装这个对象即可
1.优势:不需要每个真实类对应一个代理类这样一一对应的关系,省去了很多重复代码
2.缺点:真实类必须继承自某个接口才行用,例如上列中的drinkwater和eatbrackfast分别继承自drink接口和eat接口
Cglib代理
1.优点不需要真实类继承自某个接口,目标对象可以只是一个单独的对象。
2.缺点需要引入三方类库
(没用过,,,不评价)
kotlin 代理
kotlin中的代理使用关键字by来实现 (不过貌似没有动态代理?那有个jb用?)
public interfaceWash {// 原始的wash接口
voidwashSomth();
}
真实的实现类
open classWashDish : Wash {
valTAG:String?="KotlinProxy"
override funwashSomth() {
Log.e(TAG,"native wash somth")
}
}
代理类
classKotlinProxy(wash:Wash) :Washbywash
kotlinproxy代理类继承 并使用by关键字代理wash接口
使用时直接调用
varwashdish= WashDish()
KotlinProxy(washdish)
washdish.washSomth()
查看打印
09-07 04:58:11.912 7472-7472/? E/KotlinProxy: native wash somth