代理模式在java开发总是一种比较常见的设计模式。设计目的皆在为服务类与客户类之间插入其他功能,插入的功能对于调用者来说是透明的,起到伪装控制的作用。
今天整理了下静态代理模式和动态代理模式的一些简单的知识点。
一、Uml简图如下:
二、代理模式分为两类:静态代理和动态代理及批量代理(aop)
1.静态代理
为某个对象提供一个代理,代理角色固定,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
package com.shuaiwen.aop;
/**
* 接口 抽象角色
* 定义行为
* @author acer
*
*/
public interface Marry {
public void toMarry();
}
2.定义一个真实角色(委托类)实现上面那个接口
package com.shuaiwen.aop;
/**
* 真实角色
* 和代理角色实现同一个接口
* @author acer
*
*/
public class You implements Marry{
@Override
public void toMarry() {
System.out.println("终于等到你,还好没放弃。。");
}
}
3.定义一个代理对象(代理类)实现marry父接口
package com.shuaiwen.aop;
/**
* 创建代理对象
* 和真是角色持有相同的接口
* @author acer
* 代理类
* 1.与真实角色具有相同行为
* 2.持有真实角色的引用
* 3.增强真实角色的行为
*/
public class MarryCompany implements Marry{
//目标角色的引用
private Marry target;
// 构造方法 传入真实角色
public MarryCompany(Marry target) {
super();
this.target = target;
}
public void before(){
System.out.println("结婚前的布置。。。");
}
@Override
public void toMarry() {
// 增强真实角色行为
before();
target.toMarry();
after();
}
public void after(){
System.out.println("结婚后的感言。。。");
}
}
4.测试类
package com.shuaiwen.test;
import com.shuaiwen.aop.MarryCompany;
import com.shuaiwen.aop.You;
public class Test01 {
public static void main(String[] args) {
// 构造代理角色同时传入真实角色
MarryCompany marryCompany=new MarryCompany(new You());
marryCompany.toMarry();
}
}
结果为:
结婚前的布置。。。
终于等到你,还好没放弃。。
结婚后的感言。。。
2.动态代理
相比于静态代理,动态代理在创建代理对象上更加的灵活,它会根据需要通过反射机制在程序运行期动态的为目标对象创建代理对象,代理的行为可以代理多个方法,即满足生产需要的同时又达到代码通用的目的。
动态代理的实现有两种方式:jdk实现动态代理和cglib 动态代理实现。
1.jdk实现动态代理
package com.shuaiwen.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 制作代理的类
* @author acer
*
*/
public class JdkHandler implements InvocationHandler{
private Object target;
public JdkHandler(Object target) {
super();
this.target = target;
}
//获取动态创建的代理角色
public Object getProxy(){
//返回运行期动态创建 的代理角色
/**
* 1.类加载器
* 2.目标对象实现的接口
* 3.实现了InvocationHandler实现类
*/
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 {
//增强目标对象的行为
before();
Object result =null;
//执行目标对象的方法
result = method.invoke(target, args);
after();
return result;
}
}
测试类
package com.shuaiwen.test;
import com.shuaiwen.proxy.JdkHandler;
import com.shuaiwen.proxy.Marry;
import com.shuaiwen.proxy.You;
public class Test01 {
public static void main(String[] args) {
/**
* jdk代理对象中的真实角色必须实现相应的接口
*/
JdkHandler jdkHandler = new JdkHandler(new You());
Marry marry = (Marry) jdkHandler.getProxy();
marry.toMarry();
}
}
结果为:
结婚前的布置。。。
终于等到你,还好没放弃。。
结婚后的感言。。。
注意点:jdk代理对象中的真实角色必须实现相应的接口,否则出错。
2.cglib动态代理
code generator library ,操作字节码。 与jdk提供的代理区别:
Proxy:委托类必须有接口,制作过程比较快,执行慢;
cglib:委托类可以没有接口,继承的思维来实现相似性,制作代理过程比较慢,执行快。主要解决没有接口类的代理实现。
package com.shuaiwen.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* cglib创建动态代理
* @author acer
*
*/
public class CglibInterceptor implements MethodInterceptor{
private Object target;
public CglibInterceptor(Object 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 arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
before();
Object result = null;
result = arg3.invoke(target, arg2);
after();
return result;
}
}
测试类和上面的结果类似。。