静态代理是指代理类的代码在编译时就已经确定,也就是说,代理类的实现是由程序员手动编写的。静态代理的优点在于实现简单,易于理解和维护。但是,由于代理类的代码在编译时就确定,因此无法在运行时动态地改变代理类的行为。
在Java中,静态代理的实现方式通常是通过接口实现的。首先定义一个接口,然后编写一个实现了该接口的类,最后编写一个代理类,该代理类调用实现了接口的类的相应方法。这样,就可以通过代理类来调用实现了接口的类的方法,而不需要修改原始代码。
动态代理是指代理类的代码在运行时动态生成,也就是说,代理类的实现是由运行时环境自动生成的。动态代理的优点在于可以在运行时动态地改变代理类的行为,提高了代码的灵活性和可维护性。
在Java中,动态代理的实现方式通常是通过Java反射机制和字节码操作库(如CGLIB、Javassist等)实现的。具体来说,通过反射机制获取目标对象的类信息,然后使用字节码操作库动态生成一个实现了相同接口的代理类,该代理类在调用方法时会自动调用目标对象的方法。
优点:
缺点:
应用场景:
静态代理适用于一些功能相对固定、不需要动态改变代理类的行为的情况。例如,在某些框架中,代理类用于拦截方法调用,实现AOP(面向切面编程)等功能。
优点:
缺点:
应用场景:
动态代理适用于需要动态改变代理类的行为、扩展代理类的功能的情况。例如,在某些框架中,动态代理用于实现远程调用、事务管理、日志记录等功能。同时,在一些需要动态生成和修改代理类的场景中,也可以使用动态代理,例如在测试框架中模拟对象的行为等。
静态代理和动态代理的主要区别在于以下几个方面:
综上所述,静态代理和动态代理的主要区别在于代理类的创建时期、实现方式、扩展性、性能开销和适用场景等方面。根据实际需求选择合适的代理方式可以更好地提高代码的灵活性和可维护性。
1.抽象角色
package com.by.proxy.StaticProxy;
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
2.真正角色
package com.by.proxy.StaticProxy;
public class RealStar implements Star {
public void bookTicket() {
}
public void collectMoney() {
}
public void confer() {
}
public void signContract() {
}
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
}
}
3.代理角色
package com.by.proxy.StaticProxy;
public class ProxyStar implements Star {
private Star star;
public ProxyStar(Star star) {
super();
this.star = star;
}
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
}
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
public void confer() {
System.out.println("ProxyStar.confer()");
}
public void signContract() {
System.out.println("ProxyStar.signContract()");
}
public void sing() {
star.sing();
}
}
4.测试
package com.by.proxy.StaticProxy;
public class Client {
public static void main(String[] args) {
Star proxy = new ProxyStar(new RealStar());
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
1.抽象角色
public interface Star {
/**
* 唱歌
*/
void sing();
}
2.真正角色
package com.by.JdkProxy;
//真实角色(周杰伦)
public class RealStar implements Star {
//优点:此时代码不再重复
public void sing() {
System.out.println("周杰伦:快使用双截棍,哼哼哈嘿....");
}
}
3.代理角色
package com.by.JdkProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理类工厂
public class ProxyFactory {
//优点:此时可以代理任意类型的对象
//真实角色(周杰伦)
private Object realObj;
public ProxyFactory(Object realObj) {
this.realObj = realObj;
}
//获得代理对象
public Object getProxyObject(){
/**
* Proxy:作用创建代理对象
* ClassLoader loader:类加载器
* Class>[] interfaces:真实角色实现的接口,根据接口生成代理类
* InvocationHandler h:增强的逻辑,即如何代理(宋吉吉要做的事)
*/
return Proxy.newProxyInstance(
realObj.getClass().getClassLoader(),
realObj.getClass().getInterfaces(),
new InvocationHandler() {
/**
*
* @param proxy:代理类,一般不用
* @param method:要调用的方法
* @param args:调用方法时的参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("真正的方法执行前!");
System.out.println("面谈,签合同,预付款,订机票");
Object result = method.invoke(realObj, args);
System.out.println("真正的方法执行后!");
System.out.println("收尾款");
return result;
}
}
);
}
}
4.测试
public class Client {
public static void main(String[] args) {
//获得代理对象
Star proxyObject = (Star) new ProxyFactory(new RealStar()).getProxyObject();
System.out.println(proxyObject.getClass());//class com.sun.proxy.$Proxy0
proxyObject.sing();
}
}