1. 动态代理的作用
功能增强:在原有的功能上,增加了额外的功能,叫做功能增强。
控制访问:代理类不让你访问目标,例如商家不让用户访问厂家
2. 实现动态代理的方法
静态代理
-
代理类是自己手工实现的,自己创建一个java类,表示代理类
-
同时你所要代理的目标类是确定的
优点:实现简单,容易理解
缺点:当项目中,目标类和代理类很多时,代理类数量过多,高耦合
模拟一个用户购买U盘的行为
1. 相关设计
a.用户是客户端类 b.商家:代理,代理某个品牌的U盘 c.厂家:目标类
三者的关系:用户(客户端)——商家(代理)——厂家(目标)
商家和厂家都是卖U盘的,他们完成的功能是一致的,都是卖U盘
2. 实现步骤:
1.创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情
2.创建厂家类,实现1步骤的接口
3.创建商家,就是代理,也需要实现1步骤中的接口
4.创建客户端类,调用商家的方法买一个U盘
3. 代理类完成的功能
1.目标类中方法的调用
2.功能增强
接口
package com.txy.service;
//表示功能的,厂家商家都要完成的功能
public interface UsbSell {
//定义方法 参数 amount:表示一次购买的数量,暂时不用
//返回值表示一个U盘的价格
float sell(int amount);
}
厂家:UsbKingFactory
package com.txy.factory;
import com.txy.service.UsbSell;
//目标类:金士顿厂家,不接受用户的单独购买
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
//一个128GU盘是85元
//后期根据amount可以实现不同的价格,例如10000个,单价是80,一次买5000,单价是75
return 85.0f;
}
}
商家:TaoBao
package com.txy.seller;
import com.txy.factory.UsbKingFactory;
import com.txy.service.UsbSell;
//taobao是一个商家,代理金士顿U盘的销售
public class TaoBao implements UsbSell {
//声明 商家代理的厂家具体是谁
private UsbKingFactory factory = new UsbKingFactory();
@Override
//实现销售U盘的功能
public float sell(int amount) {
//向厂家发送订单,告诉厂家,我买了U盘,厂家发货
float price = factory.sell(amount); //厂家的价格
//商家需要加价 也就是代理要增加价格
price = price+25; //增强功能,代理类在完成目标类方法调用后,增强了功能
//在目标类的方法调用后,你做的其他功能,都是增强的意思。
System.out.println("淘宝商家,给你返回优惠价或者红包");
return price;
}
}
客户端:ShopMain
package com.txy;
import com.txy.seller.TaoBao;
public class ShopMain {
public static void main(String[] args) {
//创建代理的商家taobao对象
TaoBao taoBao = new TaoBao();
float price = taoBao.sell(1);
System.out.println("通过淘宝的商家购买U盘单价:"+price);
}
}
动态代理
在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点
动态代理中目标类即使很多,代理数量可以很少,低耦合
动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。换句话说:动态代理是一种创建java对象的能力,让你不用创建TaoBao类,就能创建代理类对象
1. 动态代理的实现
1.1 jdk动态代理:
使用java反射包中的类和接口实现动态代理的功能
反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
1.1.1 InvocationHandler接口:就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法之中
①方法原型:
public object invoke(Object proxy,Method method,Object[] args)
参数
1.Object proxy:jdk创建的代理对象,无需赋值
2.Method method:目标类中的方法,jdk提供method对象
3.Object[] args:目标类中方法的参数,jdk提供的
②怎么用:
InvocationHandler 接口:表示你的代理要干什么
1.创建实现接口InvocationHandler
2.重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这
1.1.2 Method类:
表示方法的,确切的就是目标类中的方法
作用:通过Method可以执行某个目标类的方法,Method.invoke(目标对象,方法的参数)
Object ret = method.invoke(service2,"李四");
说明:method.invoke()就是用来执行目标方法的,等同义词静态代理中的
//向厂家发送订单,告诉厂家,我买了U盘,厂家发货
float price = factory.sell(amount); //厂家的价格
1.1.3 Proxy类
核心的对象,创建代理对象。之前创建对象都是new 类的构造方法()
现在我们是使用Proxy类的方法,代替类的使用
方法:静态方法 newProxyInstance()
作用是:创建代理对象,等同于静态代理中的
TaoBao taoBao = new TaoBao();
方法原型:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
参数:
- ClassLoader loader 类加载器,负责向内存中加载对象的。使用发射获取对象的ClassLoader 例如有类a,a.getclass().getClassLoader(),(获取目标对象的类加载器)
- Class<?>[] interfaces:接口,目标对象实现的接口,也是反射获取的
- InvocationHandler h:我们自己写的,代理类要完成的功能
返回值:就是代理对象
1.1.4 具体实现
- UsbSell接口: 定义目标类和代理类都要完成的行为
package com.txy.service;
public interface UsbSell {
float sell(int amount);
}
- UsbKingFactory:目标类
package com.txy.factory;
import com.txy.service.UsbSell;
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
//目标方法
System.out.println("目标类中,执行sell目标方法");
return 85;
}
}
- MySellHandler:实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
package com.txy.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
public class MySellHandler implements InvocationHandler {
private Object target = null;
//动态代理:目标对象是活动的,不是固定的,需要传入进来
//传入是谁,就给谁创建代理
public MySellHandler(Object target) {
//给目标对象赋值
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = null;
//float price = factory.sell(amount);
res = method.invoke(target,args);//执行目标方法
//price = price + 25;
//增强功能
if(res != null){
Float price = (Float)res;
price = price+25;
res = price;
}
System.out.println("淘宝商家,给你返一个优惠劵,或者红包");
return res;
}
}
- MainApp
package com.txy
import com.txy.factory.UsbKingFactory;
import com.txy.handler.MySellHandler;
import com.txy.service.UsbSell;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainShop {
public static void main(String[] args) {
//创建代理对象,使用Proxy
//1. 创建目标对象
//也可以UsbKingFactory factory = new UsbKingFactory();但是接口接会更好
UsbSell factory = new UsbKingFactory();
//2. 创建invocationHandler对象
InvocationHandler invocationHandler = new MySellHandler(factory);
//2. 创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
invocationHandler);
//4. 通过代理执行方法
float price = proxy.sell(1);
System.out.println("通过动态代理调用方法结果是"+price);
}
}
1.1.5 流程图
1.2 cglib动态代理:
cglib是第三方的工具库,创建代理对象
cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类同名的方法,实现功能的修改。
因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的
具体实现
- Target 目标类
package com.txy.proxy.cglib;
public class Target{
public void save() {
System.out.println("save save save hey running....................");
}
}
- Advice 增强类
package com.txy.proxy.cglib;
public class Advice {
public void before(){
System.out.println("前置增强...................");
}
public void after(){
System.out.println("后置增强...................");
}
}
- 代理实现
package com.txy.proxy.cglib;
import com.txy.proxy.jdk.TargetInterface;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//增强对象
final Advice advice = new Advice();
//返回值 就是动态生成的代理对象 基于cglib
//1. 创建增强器
Enhancer enhancer = new Enhancer();
//2. 设置父类(目标)
enhancer.setSuperclass(Target.class);
//3. 设置回调 MethodInterceptor是Callback的一个实现类
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
advice.before();//前置增强
Object res = method.invoke(target, args);//执行目标
advice.after();//后置增强
return null;
}
});
//4. 创建代理对象
Target proxy = (Target)enhancer.create();
proxy.save();
}
}
对于无接口的类,要使用cglib来实现
hodProxy) throws Throwable {
advice.before();//前置增强
Object res = method.invoke(target, args);//执行目标
advice.after();//后置增强
return null;
}
});
//4. 创建代理对象
Target proxy = (Target)enhancer.create();
proxy.save();
}
}
**对于无接口的类,要使用cglib来实现**