代理模式(Proxy)
为对象提供代理,以控制对这个对象的访问
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以起到两者之间的中介作用
代理模式设计原则
代理类与真实委托类拥有相似的行为
代理类增强委托类的行为
静态代理
为对象提供代理,代理的角色固定
代理类与委托类实现共同接口,使代理类可以代替委托类
代理类负责委托类实现功能的前提准备,以及实现功能后的后续处理
静态代理对于代理的角色固定,一旦需要代理的角色数量增加,则代理类也需要相应的增加
静态代理的简单实现
//声明共同抽象接口,定义行为
public interface RentingAHouse{
//真实委托人的实际行为
public void renting();
}
//定义委托类(真实角色)
public class Landlord implements RentingAHouse{
@Override
public void renting(){
System.out.println("签合同,租房成功");
}
}
/*
代理类
与委托类实现共同接口
持有委托类的引用
增强委托类的行为
*/
public class Agent implements RentingAHouse{
//委托类的引用
private Landlord target;
public void Agent(Landlord target){
this.target = target;
}
//代理类的增强行为
public void before(){
System.out.println("给客户介绍房子,带客户看房");
}
public void after(){
SysTem.out.println("后续服务...");
}
@Override
public void renting(){
before();
target.renting();
after();
}
}
/*
代理实例
*/
public class Test{
public static void main(String[] args){
//实例代理角色,引入真实角色
Agent agent = new Agent(new Landlord());
//实现代理类增强后的真实行为
agent.renting();
}
}
动态代理
静态代理在需要代理的数量过多时满足不了生产需求,则衍生更加灵活的动态代理
动态代理根据反射机制在程序运行期动态的为目标对象创建代理对象
可以代理多个方法,能满足生产需要,还能实现代码通用
JDK动态代理
jdk代理中委托类必须实现接口
jdk动态代理制作代理过程较快,执行较慢
/*
jdk动态代理
*/
public class JDKHandler implements InvocationHandler{
//委托类
private Landlord target;
public void JDKHandler(Landlord target){
this.target = target;
}
/*
创建动态代理角色
1,获取类加载器
2,获取委托类实现的接口
3,当前类
*/
public Object getProxy(){
return Proxy.newProxyInstance(
//获取类加载器
this.getClass().getClassLoader(),
//获取委托类实现的接口
target.getClass().getInterfaces(),
//当前类
this
);
}
//代理类的增强行为
public void before(){
System.out.println("给客户介绍房子,带客户看房");
}
public void after(){
SysTem.out.println("后续服务...");
}
@Override
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
Object result = null;
before();
//执行真实角色方法
result = method.invoke(target,args)
after();
teturn result;
}
}
/*
jdk动态代理实现
*/
public class Test01{
public static void main(String[] args){
JDKHandler jdkHandler = new JDKHandler(new Landlord());
//动态获取代理类(多态)
RentingAHouse proxy = (RentingAHouse) jdkHandler.getProxy();
//实现代理类增强后的真实行为
proxy.renting();
}
}
CgLib动态代理(code generator library )
CgLib动态代理的委托类可以没有实现接口,通过继承概念实现相似性
CgLib动态代理的制作代理过程较慢,执行快,主要解决没有接口类的代理
<!-- CgLib需要引入jar包 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.1</version>
</dependency>
/*
CgLib动态代理
*/
public class CgLibInterceptor implements MethodInterceptor{
//委托类
private Landlord target;
public void JDKHandler(Landlord target){
this.target = target;
}
//动态创建代理类
public Object getProxy(){
Enhancer enhancer = new Enhancer();
//设置父类与继承类
enhancer.setSuperClass(target.getClass());
enhancer.setCallBack(this);
//返回创建的代理类
return enhancer.create();
}
//代理类的增强行为
public void before(){
System.out.println("给客户介绍房子,带客户看房");
}
public void after(){
SysTem.out.println("后续服务...");
}
@Override
public Object intercept(Object o,Method method,Object[] objects,MethodProxy methodProxy)throws Throwable{
Object result = null;
before();
//执行真实角色方法
result = method.invoke(target,objects);
after();
return result;
}
}
/*
CgLib动态代理实现
*/
public class Test01{
public static void main(String[] args){
CgLibInterceptor cgLibInterceptor = new CgLibInterceptor(new Landlord());
Landlord proxy = (Landlord) cgLibInterceptor.getProxy();
proxy.renting();
}
}