什么是代理?
定义:给目标对象提供一个代理对象,并用代理对象控制对目标对象的引用
使用代理目的:
①:功能增强:通过代理业务对原有业务进行增强
②:控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性
实现代理的两种方式
一、静态代理
1.静态代理特点
①:代理类是自己手动实现的,需要自己去创建一个类
②:代理类所代理的目标类是固定的
2.利用接口实现静态代理
关于接口的方式,我们在实现接口的时候,目标类和代理类都必须实现目标接口当中所实现的方法,从某种意义上代理类就可以帮我们实现目标类当中的方法,并且代理类还可以有自己的扩展方法。
3.代码实现
首先先定义接口
public interface ByClothes {
void clothes(String size);
}
定义目标对象
public class ClothesFactory implements ByClothes {
public void clothes(String size) {
System.out.println("已制定好一件大小为" + size + "的衣服");
}
}
制造代理对象
/**
* 代理类
*/
public class Proxy implements ByClothes {
//被包含的真是对象
private ClothesFactory clothesFactory = new ClothesFactory();
// 对功能的增强
@Override
public void clothes(String size) {
frontService();
clothesFactory.clothes(size);
endService();
}
//前置服务
public void frontService(){
System.out.println("店员服务");
}
//前置服务
public void endService(){
System.out.println("售后服务");
}
}
测试类
public class Test {
public static void main(String[] args) {
Proxy p = new Proxy();
p.clothes("xx");
}
}
结果
4.静态代理逻辑图
5.静态代理存在的问题
①:当目标类曾多时,代理类也需要增多,导致代理类的关系不便。
②:当接口当中的功能增多或者修改,都会影响实体类,违反开闭原则(程序对访问开放,对修改关闭)
二、动态代理
1.静态代理和动态代理的区别
静态代理需要我们手动的去创建代理对象,动态代理则是采用jdk提供的方法创建代理对象
2.动态代理的实现
①:jdk动态代理:使用java反射包当中的类和接口实现动态代理的功能
②:cglib动态代理:cglib是是第三方的工具库。其原理是继承,cglib通过继承目标类,创建他的子类,在子类当中重写父类的相关方法,实现功能的增强。
(1).jdk动态代理
新建接口
//接口的目的是告诉代理对象代理那个方法
public interface ByClothes {
/**
* 制造衣服的方法
* @param size 衣服的大小
*/
void clothes(String size);
}
public interface ByShoot {
void byShoot(String size);
}
新建对应工厂
public class ClothesFactory implements ByClothes{
public void clothes(String size){
System.out.println("已制定好一件大小为"+size+"的衣服");
}
}
public class ShootFactory implements ByShoot{
@Override
public void byShoot(String size) {
System.out.println("已经为您生产出了尺码为"+size+"的鞋子");
}
}
代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory implements InvocationHandler {
private Object factory ; //被代理对象的引用
public Object getFactory(){
return factory;
}
public void setFactory(Object factory){
this.factory = factory;
}
//反射执行方法
//1.Object :jdk创建的代理类,无需赋值
//2.Method : 目标类当中的方法,jdk提供,不需要赋值
//3.Object[]:目标类当中的方法参数 ,jdk提供,不需要赋值
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
FrontService();
method.invoke(factory,args);//执行目标类当中的方法
endService();
return null;
}
public void FrontService() {
System.out.println("根据您的需求进行市场调研");
}
//前置服务
public void endService() {
System.out.println("为您提供一条龙的包办服务");
}
//该方法并不是固定的,但是内部的Proxy类的创建是核心
/**
* 1.ClassLoader loader : 类的加载器:像内存当中加载对象,使用反射的方式获取
* 2.Class<?>[] interfaces:获取目标类的接口,使用反射的方式获取---------》方法
* 3.InvocationHandler h:让代理类知道被代理的方法
* @return
*/
public Object getProxyInstance() {
// TODO Auto-generated method stub
return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
}
}
代理类细节
①:InvocationHandler接口:里边只有一个invoke()方法
invoke()方法:表示我们要求代理对象要完成的功能
1).调用并执行目标的方法
2).功能增强,在目标对象调用时增强其功能
②:Proxy类:核心对象,其目的是创建道理对象
以前我们创建对象是new构造器,现在我们使用Proxy类的方法,代理new的使用
newProxyInstance()方法的作用是创建代理对象,其返回值就是代理对象
//ClassLoader loader:类的加载器,复杂向内存当中加载对象,使用反射的方式获取
// Class<?>[] interfaces:目标对象实现的接口,也是反射获取
//InvocationHandler h:代理类需要完成的功能 public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
测试类
public class Test {
public static void main(String[] args) {
ProxyFactory proxy = new ProxyFactory();
ClothesFactory clothesFactory = new ClothesFactory();
proxy.setFactory(clothesFactory); //告诉了我们代理类要代理的类
ByClothes ByClothes = (ByClothes) proxy.getProxyInstance();
ByClothes.clothes("XXL");
ShootFactory shootFactory = new ShootFactory();
proxy.setFactory(shootFactory);
ByShoot byShoot = (ByShoot) proxy.getProxyInstance();
byShoot.byShoot("45");
}
}
结果