代理模式 Proxy Pattern
Provide a surrogate or placeholder for another object to control access to it.
为其他对象提供一种代理以控制对这个对象的访问。
«Java设计模式»
1.静态代理
静态代理是指 代理类在程序运行前就已经定义好,其与目标类的关系在程序运行前就已经确立。
怎么区分静态代理和动态代理呢
如果有代理类 说明程序启动时就加载了 是静态代理
动态代理没有代理类 代理对象是通过工厂或者工具类生成的。
静态代理在使用时,需要定义接口或父类,被代理对象与代理对象一起实现接口或者继承相同父类。
举个栗子:
public interface ISomeService{
String doFirst();
void doSecond();
}
//被代理类
public class SomeServiceImpl implements ISomeService{
public String doFirst(){
System.out.println("执行了doFirst方法");
String result = "azheng";
System.out.println("result = " + result);
return result;
}
public void doSecond(){
System.out.println("执行doSecond方法");
}
}
//代理类
//这里实现将doFirst()返回的字符串转大写功能
public class SomeServiceProxy implements ISomeService(){
public String doFirst(){
ISomeService service = new SomeServiceImpl();
String result = service.doFirst();
return result.toUpperCase();
}
public void doSecond(){
//这里不做功能扩展
}
}
//测试代理类
public class MyTest(){
public void main(String args[]){
ISomeService service = new SomeServiceProxy();
String result = service.doFirst();
System.out.println("result = " + result);
service.doSecond();
}
}
输出结果:被代理类执行了doFirst方法
result = AZHENG
执行doSecond方法
2.动态代理
代理类在程序运行时创建的代理方式被成为 动态代理。
动态代理又分为两种方式,
- 1.通过jdk的Proxy动态代理
要求目标类与代理类必须实现相同接口,如目标类米有接口,则不能用这个方法。
因为底层执行原理,与静态代理的相同
栗子来了:
//接口还是那个接口
public interface ISomeService {
String doFirst();
void doSecond();
}
//被代理类也还是那个被代理类
public class SomeServiceImpl implements ISomeService{
public String doFirst(){
System.out.println("执行了doFirst方法");
String result = "azheng";
System.out.println("result = " + result);
return result;
}
public void doSecond(){
System.out.println("执行doSecond方法");
}
}
//不过这里就没有SomeServiceProxy()代理类了,直接实现了接口
//MyTest.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.azheng.service.ISomeService;
import com.azheng.service.SomeServiceImpl;
public class MyTest{
public void main(String args[]){
final ISomeService target = new SomeServiceImpl();
ISomeService service = (ISomeService)Proxy.newProxyInstance(
target.getClass().getClassLoader(), //目标类的类加载器
target.getClass().getInterfaces(), //目标类所实现的所有接口
new InvocationHandler(){ //匿名内部类
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
//proxy 代理对象
//method 目标方法
//args 目标方法的参数列表
Object result = method.invoke(target,args);
if(result != null){
result = ((String)result).toUpperCase();
return result;
}
return null;
}
});
String result = service.doFirst();
System.out.println("result = " + result);
service.doSecond();
}
}
输出结果:被代理类执行了doFirst方法
result = AZHENG
执行doSecond方法
- 2.cglib动态代理(Code Generation Library)
这是对于米有接口的类,要使用cglib。
cglib也可以实现代理有接口的目标类。
cglib代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。
但是也有条件,目标类必须是可继承的,不能是fianl的。
在这里用的是这个jar包 : cglib-full.jar
//接口就米有了
//目标类
public class SomeService{
public String doFirst() {
System.out.println("执行doFirst方法");
return "azheng";
}
public void doSecond() {
System.out.println("执行doSecond方法");
}
}
//代理类
public class MyCglibFactory implements MethodInterceptor{
private SomeService target;
public MyCglidFactory{
target = new SomeService();
}
public SomeService myCglibCreator(){
//创建增强器对象
Enhancer enhancer = new Enhancer();
//制定目标类,即父类
enhancer.setSuperClass(SomeService.class);
//设置回调接口对象
enhancer.setCallbabk(this);
//返回的是子类,即代理对象
return (SomeService)enhancer.create();
}
//回调方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable{
Object result = method.invoke(target, args);
if (result != null) {
return result = ((String) result).toUpperCase();
}
return null;
}
}
//MyTest
import com.azheng.factory.MyCglibFactory;
import com.azheng.service.SomeService;
public class MyTest {
public static void main(String[] args) {
SomeService service = new MyCglibFactory().myCglibCreator();
String result = service.doFirst();
System.out.println("result = " + result);
service.doSecond();
}
}
输出结果同上
瞅瞅为啥是回调方法
到这里就结束啦~
只有让自己变得更强 才会无所畏惧