1.静态代理
1.代理模式
实现原理:代理类和真实类都实现同一个接口,实际还是依赖真实类去实现功能
1.1代理模式代码
package com.amarsoft.designmode.proxy;
/**
* 代理模式:提供一个统一的接口,具体的实现类和代理类都实现该接口,用于代理类可以完成具体类相同的方法
* @author amarsoft
*
*/
public interface Subject {
//统一的方法
void request();
}
----------------------------------------------------
package com.amarsoft.designmode.proxy;
/**
* 代理类
* @author 小虾
*/
public class Proxy implements Subject{
//被代理的类
public RealSubject subject ;
@Override
public void request() {
System.out.println("proxy implements ways...");
if(subject ==null) {
subject = new RealSubject();
}
//调用真实类中的方法
subject.request();
}
}
--------------------------------------------------------
package com.amarsoft.designmode.proxy;
/**
* 真实类
* @author 小虾
*
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("realSubject implements ways ...");
}
}
------------------------------------------
package com.amarsoft.designmode.proxy;
/**
* designmode
* 代理的主入口测试类
* @author amarsoft
* 静态代理:需要自己去实现代理类。
*
*/
public class ProxyMain {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}
1.2代理模式案例
案例:通过中介买房
1.2.1案例代码
package com.amarsoft.designmode.proxy.demo;
/**
* 买房接口
* @author 小虾
*/
public interface BuyHouseInterface {
void buy();
}
------------------------------------------------
package com.amarsoft.designmode.proxy.demo;
/**
* 真实买房对象
* @author 小虾
*
*/
public class SubjectBuyHouse implements BuyHouseInterface{
@Override
public void buy() {
System.out.println("我自己在成都买房");
}
}
------------------------------------------
package com.amarsoft.designmode.proxy.demo;
/**
* 代理购房:实际调用具体购房者的买房方法
* @author
*
*/
public class ProxyBuyHouse implements BuyHouseInterface{
//具体的买房的人
private SubjectBuyHouse buyHoser ;
public ProxyBuyHouse(SubjectBuyHouse buyHoser) {
this.buyHoser = buyHoser;
}
@Override
public void buy() {
System.out.println("中介帮忙买房子赚差价");
buyHoser.buy();
System.out.println("中介成功赚取差价");
}
public static void main(String[] args) {
ProxyBuyHouse proxy = new ProxyBuyHouse(new SubjectBuyHouse());
proxy.buy();
}
}
//运行结果
中介帮忙买房子赚差价
我自己在成都买房
中介成功赚取差价
1.3 静态代理总结
实际上,真正的功能还是有真实的目标类来实现的,代理类扩展争强目标类的行为
二.动态代理
2.1 JDK动态代理
- 实现invocationHandle,重写invoke();
package com.amarsoft.designmode.proxy.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.amarsoft.designmode.proxy.demo.BuyHouseInterface;
import com.amarsoft.designmode.proxy.demo.SubjectBuyHouse;
/**
*
* jdk 的动态代理:
* @author
*
*/
public class JDKProxy implements InvocationHandler{
//被代理的类
public Object tarjet ;
public JDKProxy(Object tarjet) {
this.tarjet = tarjet;
}
@Override
public Object invoke(Object proxy, Method method, Object[] objs) throws Throwable {
System.out.println("中介自动代理买房");
Object invoke = method.invoke(tarjet, objs);
System.out.println("中介自动代理买房成功");
return invoke;
}
public static void main(String[] args) {
//需要被代理的类
SubjectBuyHouse sbh = new SubjectBuyHouse();
JDKProxy proxyBuyHouse = new JDKProxy(sbh);
//参数:需要被代理的类的 类加载器,class和代理 类InvocationHandler
BuyHouseInterface buy = (BuyHouseInterface) Proxy.newProxyInstance(sbh.getClass().getClassLoader(),
sbh.getClass().getInterfaces(), proxyBuyHouse);
buy.buy();
}
}
//运行结果:
/**
* 中介自动代理买房
我自己在成都买房
中介自动代理买房成功
*/
动态代理:
为接口创建代理类的字节码文件,使用ClassLoader将字节码文件加载到JVM;创建代理类实例对象,执行对象的目标方法;
2.2cglib动态代理
2.2.1案例
package spring.cglib.demo;
/**
* 具体的买房客户类
* @author 小虾
*
*/
public class SubjectCustomer {
//买房
public void buy(){
System.out.println("我是买房客户,自己在成都买房");
}
//租房
public void rent(){
System.out.println("我是[租房]客户,自己在成都租房");
}
}
--------------------------------------------------------------------
package spring.cglib.demo;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* 租房
* @author 小虾
*
*/
public class RentHouseProxy implements MethodInterceptor {
//需要被代理的类
private Object obj ;
public RentHouseProxy(Object obj) {
this.obj = obj;
}
@Override
public Object intercept(Object o, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//invoke:被代理的类,外部传入的;args:参数
System.out.println("我是[租房]代理");
Object object = methodProxy.invoke(obj, args);
return object;
}
}
----------------------------------------
package spring.cglib.demo;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* @author 小虾
*
*/
public class BuyHouseProxy implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("我是买房代理");
Object object = methodProxy.invokeSuper(obj, args);
return object;
}
}
----------------------------------------------------------------------
package spring.cglib.demo;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
/**
* cglib 租房买房 多映射类
* @author 小虾
*
*/
public class CgilbHouseTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SubjectCustomer.class);
SubjectCustomer customer = new SubjectCustomer();
//callback 只有一个参数
//enhancer.setCallback(new BuyHouse());
// callback 有多个参数 :租房;买房
enhancer.setCallbacks(new Callback [] {new BuyHouseProxy(),new RentHouseProxy(customer)});
enhancer.setCallbackFilter(new CallbackFilter() {
//通过方法区分调用某个类
@Override
public int accept(Method method) {
if(method.getName().equals("rent")){
return 1 ;
}else{
return 0;
}
}
});
//调用动态代理的方法
SubjectCustomer customerProxy = (SubjectCustomer)enhancer.create();
customerProxy.rent();
customerProxy.buy();
}
}
2.2.2 cglib动态代理总结
- 实现MethodInterceptor,重写intercept();
- intercept()有两个方法,invoke(“传入的被代理的类”,参数)和invokeSuper(“intercept中的object”,参数),两个方法上面案例中都有使用,可以具体参考上面案例。
- Enhancer 可以有根据方法名称,有多个回调。setCallbacks()配合setCallbackFilter(),可以调用不同的代理类.
JDK和cglib动态代理区别
- java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理;cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
- JDK动态代理只能对实现了接口的类生成代理;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
结束:
快过年了,祝各位都事事顺利。有问题的帮忙指正。
来源:CSDN
作者:小虾~半月劫
链接:https://blog.csdn.net/qq_38684778/article/details/104060680