目录
目标对象不可访问,通过代理对象增强功能访问,实现访问目标对象。如:租房子,需要通过房屋中介来实现租房。目标对象:房东,代理对象:中介,客户端对象:租客。
1)控制目标对象的访问
2)增强功能
1),静态代理
2)。动态代理
a,JDK动态代理
b,CGLib动态代理
代理模式的一种,
1)目标对象和代理对象实现同一个业务接口
2),目标对象必须实现接口
3),代理对象在运行前就已经存在
4),能够灵活切换目标对象,却无法进行功能的灵活处理(使用动态代理处理)
1,内部成员属性定义为接口类型,2,方法的返回值定义为接口,3,方法的参数定义为接口
灵活的进行功能切换的要求
静态代理:能够灵活切换目标对象,却无法进行功能的灵活处理(所以要使用使用动态代理处理)
代理对象在程序运行时动态在内存构建,可以灵活的进行业务切换。
a,目标对象必须实现业务接口
b,JDK代理对象不需要实现业务接口
c,JDK动态代理的对象,在程序运行前不存在,在程序运行时,动态的在内存构建
d,JDK灵活的进行任务切换。
e,本类中的自己的方法,不可以被代理
java.lang.reflect.Proxy包下的类
Proxy.newProxyInstance(.....)
newProxyInstance(...)的参数解读:
ClassLoader://类加载器
Class>[] :目标对象实现的全部接口
InvocationHandler:代理的功能和目标对象业务的实现都在该接口下的实现类中
反射用的类,用来进行对目标对象的方法的反射调用。
method.invoke();//调用方法
实现代理的功能和调用目标对象重写接口的方法,使用匿名内部类来实现
业务接口:
- public interface Service {
- void buy();
- String getName(String name);
- }
目标对象1:
- public class Women implements Service {
- @Override
- public void buy() {
- System.out.println("买小裙子。。。。");
- }
-
- @Override
- public String getName(String name) {
- System.out.println(name);
- return name;
- }
- }
目标对象2:
- public class Man implements Service {
- @Override
- public void buy() {
- System.out.println("买包华子。。。");
- }
-
- @Override
- public String getName(String name) {
- return name;
- }
- }
代理工厂:程序运行时动态的创建代理对象
- public class ProxyFactory {
- Service service;
- public ProxyFactory(Service service){
- this.service = service;
- }
-
- //获取JDK动态代理对象
- public Object getAgent(){
- return Proxy.newProxyInstance(
- service.getClass().getClassLoader(),//获得目标对象的类加载器
- service.getClass().getInterfaces(),//获得目标对象的实现的所有接口
- new InvocationHandler() {//动态代理对象的功能
- @Override
- public Object invoke(
- Object proxy,//创建动态代理对象
- Method method,//代理对象需要调用的方法
- Object[] args//目标方法的参数
- ) throws Throwable {
- //代理功能
- System.out.println("去商场");
- //目标对象功能,args是方法运行需要的参数
- Object invoke = method.invoke(service, args);
- //代理功能
- System.out.println("买到了");
- return invoke;//返回目标方法的返回值
- }
- }
- );
- }
- }
测试:
- public static void main(String[] args) {
- Service service = new Women();
-
- //这里不能传入实现类的匿名对象,需要先将实现类的类型提升为接口,在将替身后的对象传入,否则会出现类型转换异常
- ProxyFactory factory = new ProxyFactory(service);
-
- Service agent = (Service) factory.getAgent();
-
- //这里得到的对象类型是:class com.sun.proxy.$Proxy0
- System.out.println(agent.getClass());
-
- //因为他是Proxy类型的对象,所以除了这个接口的方法,实现类自己的方法是无法通过该对象来调用的
- agent.buy();
- agent.getName("张三");
-
- }
通过动态的在内存中构建子类对象,重写父类的方法,进行代理功能的增强
即在实现类没有实现接口时,通过CGLib子类代理来进行功能加强。(有点像继承)