对于java业务而言,通常会把主体业务和枝节性代码分开,比如做数据库更新的时候,会把事务的管理和真正的业务逻辑分开,这样既提高了管理类的使用效率,也降低了管理类和业务的耦合。类似的情况还有日志记录、信息监管等。
代理模式:为其它对象提供一种代理以控制对这个对象的访问。代理模式的角色:
- 抽象角色:声明真实对象和代理对象的共同接口
- 代理角色:代理对象内部包含有真实角色的引用,从而可以操作真实角色,同时代理对象 与真实对象有相同的接口,能在任何时候代替真实对象,同时代理对象可以在执行真实对 象前后加入特定的逻辑以实现功能的扩展。
- 真实角色:代理角色所代表的真实对象
java中代理的实现:
1、静态代理,为每一个真实对象特定生成一个代理类
// 接口
public interface Int {
void doJob(String jobName);
}
//实现类
public class IntImpl implements Int {
private String jobName;
public IntImpl() {
}
public IntImpl(String jobName) {
this.jobName = jobName;
}
public void doJob(String jobName) {
System.out.println(this.getClass().getSimpleName()+" start to do job "+ jobName);
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
}
// 静态代理实现类
public class StaticProxy implements Int{
private Int intService;
public StaticProxy(Int intService) {
this.intService = intService;
}
public void doJob(String jobName) {
System.out.println(" proxy class "+this.getClass().getSimpleName()+" do job");
this.intService.doJob(jobName);
}
}
2、动态代理在运行时生成
public class DynamicProxyHandler implements InvocationHandler{
private Object targetObject;
public Object bindProxy(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("dynamic method");
return method.invoke(targetObject,args);
}
}
3、cglib字节码代理public class CglibProxy implements MethodInterceptor {
public Object getInstance(Object target){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置代理");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("后置代理");
return result;
}
}
cglib和invocationHandler实现区别:
1、jdk动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。jdk代理只能代理接口,会根据接口生成一个与实现类同级的代理接口子类,目标对象作为代理对象的一个属性。
2、cglib代理动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理,方法调用时,通过子类方法覆盖父类方法,所以方法不能是final声明。