代理:是一种设计模式,提供了对目标对象另外的访问方式
有些对象没法直接访问,利用代理对象间接访问
代理的好处:
1、目标对象可以间接方法文
2、代理的主要作用就是增强(代理的范围比目标对象大,可以在目标对象实现的基础上,在代理的范围内增强额外功能,即扩展目标对象的功能)
3、(当功能有些不足或者代码有些不完善)不要随意修改原有代码,如果需要修改,可以通过代理去扩展(团队开发时尤其重要)(当需要更丰富的功能时调用代理,需要本质功能调用原有方法)
代理的种类
静态代理
只能对固定类进行代理还需要修改源代码
接口实现静态代理
例子1:代购帮忙买东西
1、首先创建目标类接口(代理类目标类都要实现这个接口)
package Test121.Test428;
//目标接口
public interface ByClothes {
void clothes(String size);
void like(String x);
}
2、目标类实现接口
package Test121.Test428;
//目标类
public class ClothesFactory implements ByClothes{
@Override
public void clothes(String size) {
System.out.println("已经为您制作了"+size+"尺寸的衣服");
}
@Override
public void like(String x) {
System.out.println("你最喜欢的衣服是"+x);
}
}
3、代理类实现接口,并添加额外的功能
package Test121.Test428;
public class ClothesProxy implements ByClothes{
//目标对象
public ClothesFactory clothesFactory;
public ClothesProxy(ClothesFactory clothesFactory) {
this.clothesFactory = clothesFactory;
}
@Override
public void clothes(String size) {
//可以在目标方法实现过程中,定义一些额外的功能
frontService();
//这是目标对象方法
clothesFactory.clothes(size);
//额外功能
endService();
}
@Override
public void like(String x) {
clothesFactory.like(x);
}
//售前服务
public void frontService(){
System.out.println("根据您的需要进行产品研发");
}
//售后服务
public void endService(){
System.out.println("产品已交付您,后续有任何问题,随时联系");
}
}
4、测试类测试代码
package Test121.Test428;
public class Test {
public static void main(String[] args) {
ClothesFactory clothesFactory = new ClothesFactory();
ClothesProxy clothesProxy = new ClothesProxy(clothesFactory);
clothesProxy.clothes("xxl");
clothesProxy.like("短袖");
}
}
动态代理
动态代理(底层用了反射,利用反射可以实现对其他类(可以对许多类)的代理不需要改源代码)
java中一个类想拿另外一个类的全部一般来说就是继承和接口两种方式
jdk动态代理
不需要额外安装包,jdk动态代理实现代理通过(底层)接口实现
CGLIB动态代理
需要导入额外的java包,调用其中的一些方法(底层是靠继承)
例子2:代购生意做大了,创建了一个代购公司一个代购公司会代购许多不用的商品
company(jdk动态代理):
package Test121.Test428;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Company implements InvocationHandler {
//目标对象
private Object factory;
public Object getFactory() {
return factory;
}
public void setFactory(Object factory) {
this.factory = factory;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//额外功能
frontService();
Object obj = method.invoke(factory,args);//反射实现方法
//额外功能
endService();
return null;
}
//售前服务
public void frontService(){
System.out.println("根据您的需要进行产品研发");
}
//售后服务
public void endService(){
System.out.println("产品已交付您,后续有任何问题,随时联系");
}
//获取代购员
public Object getProxyInstance(){
/反射返回一个(符合后续条件的)对象
//factory.getClass().getInterfaces()里面是一个数组形式的数据
// 所以上面method.invoke(factory,args)调用方法其实是遍历数组知道找到名字是调用名的方法
//Proxy.newProxyInstance(factory.getClass().getClassLoader()这里面在创建对象过程中调用了invoke方法
return Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);
}
}
测试:
package Test121.Test428;
public class Test {
public static void main(String[] args) {
// ClothesFactory clothesFactory = new ClothesFactory();
// ClothesProxy clothesProxy = new ClothesProxy(clothesFactory);
// clothesProxy.clothes("xxl");
// clothesProxy.like("短袖");
//目标对象
ClothesFactory clothesFactory = new ClothesFactory();
//目标对象
ShootFactory shootFactory = new ShootFactory();
//代购公司
Company company = new Company();
//为代购公司设置目标对象
company.setFactory(shootFactory);
//获取到了一个具体的能代购“factory(具体代购的目标对象)”的代购员
ByShoot good1 = (ByShoot) company.getProxyInstance();//强转因为获取到的目标是Object类型
good1.shoot("45");
}
}
鞋子类:
package Test121.Test428;
public class ShootFactory implements ByShoot{
@Override
public void shoot(String size) {
System.out.println("您买的鞋子的尺寸是:"+size);
}
}