说明;
对前一篇 老僧长谈设计模式-7-代理模式 的补充
1.静态代理模式
讲一个说话和唱歌的故事,
你有一个接口ITalk,接口中有一个方法talk(),然后你还有一个Real Request类实现了ITalk接口。
但是光是说话满足不了全部人的要求,有的人还喜欢唱歌。
怎么办?难道在接口中再增加sing()方法吗?不可能的,那样的话所有该接口的实现类都不得不实现该方法啦。
此时一个聪明的办法是写一个代理类TalkProxy,其中不光有talk(),而且还有sing();
Proxy类
/**
* 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
*
* @author yanbin
*
*/
public class TalkProxy implements ITalk {
private ITalk talker;
public TalkProxy(ITalk talker) {
// super();
this.talker = talker;
}
public void talk(String msg) {
talker.talk(msg);
}
/**
* good,重载方法巧妙调用sing()
* @param msg
* @param singname
*/
public void talk(String msg, String singname) {
talker.talk(msg);
sing(singname);
}
private void sing(String singname) {
System.out.println("唱歌:" + singname);
}
}从这段代码可以看出来,代理模式其实就是AOP的雏形。 上端代码中talk(String msg, String singname)是一个切面。在代理类中的sing(singname)方法是个后置处理方法。
测试类
/**
* 代理测试类,使用代理
*
* @author yanbin
*
*/
public class ProxyPattern {
public static void main(String[] args) {
// 不需要执行额外方法的。
ITalk people = new PeopleTalk("AOP", "18");
people.talk("No ProXY Test");
System.out.println("-----------------------------");
// 需要执行额外方法的(切面)
ITalk talker = new new TalkProxy(people);
talker.talk("ProXY Test", "千里之外");
}
}
2.动态代理模式InvocationHandler
jdk1.5中提供,利用反射。实现java.lang.reflect.InvocationHandler接口
①必须要有一个业务接口
/**
* @author
* @version V1.0
* @Date
* @Email
* @Description: 抽象主题角色 Subject
*/
public interface ITalk {
public void talk(String msg);
}②接口实现类
/**
* @author
* @version V1.0
* @Date
* @Email
* @Description: Real Request
*/
public class PeopleTalk implements ITalk {
private String username;
private String age;
public PeopleTalk() {
this("James", "30");
}
public PeopleTalk(String username, String age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public void talk(String msg) {
// TODO Auto-generated method stub
System.out.println(msg + "!你好,我是" + this.getUsername() + ",年龄" + this.getAge());
}
}③动态代理类
/**
* @author
* @version V1.0
* @Date
* @Email
* @Description: 动态代理
*/
public class DynamicProxy implements InvocationHandler {
/*需要代理的目标类*/
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
// TODO Auto-generated method stub
this.target = target;
/**
* 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
* @param loader - 定义代理类的类加载器
* @param interfaces - 代理类要实现的接口列表
* @param h - 指派方法调用的调用处理程序 InvocationHandler类invoke()方法
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
* @param Object proxy 被代理的对象
* @param Method method 要调用的方法
* @param Object[] args 方法调用时需要的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result = null;
//切面之前执行
System.out.println("切面之前执行.");
//执行业务
result = method.invoke(target, args);
//切面之后执行
System.out.println("切面之后执行.");
return result;
}
}④测试类
/**
* @author
* @version V1.0
* @Date
* @Email
* @Description: 代理测试类
*/
public class ProxyTest {
public static void main(String[] args) {
ITalk talk = (ITalk) new DynamicProxy().bind(new PeopleTalk());
talk.talk("业务说明");
}
}3.动态代理Cglib
CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式。
使用范围:对于不适用接口的业务类,无法使用JDK动态代理
原理:CGlib采用非常底层的字节码技术,可以为一个类创建子类,解决无接口类的代理类问题。
①业务类,不实现任何的接口
/**
* 该业务类没有实现任何接口
* @author dell
*
*/
public class Cat {
public void run(){
System.out.println("猫可以跑步。。。捉老鼠");
}
} ②动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.Test;
public class ProxyTest {
@Test
public void demo2(){
// cglib 动态代理 在目标业务类没有实现接口的情况下
// 1、创建真实业务对象的引用
Cat cat = new Cat();
// 2、创建真实业务类的子类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cat.getClass());
// 3、设置回调函数
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("run")){
System.out.println("cat的run方法被拦截了。。。。");
Object invoke = method.invoke(proxy, args);
System.out.println("真实方法拦截之后。。。。");
return invoke;
}
// 不拦截
return method.invoke(proxy, args);
}
});
Cat proxy = (Cat) enhancer.create();
proxy.run();
}
}
----------------------------------------------------------------------------
来源参考http://blog.youkuaiyun.com/mrzhoug/article/details/51336833
设计模式(1)--理解AOP(代理模式)
http://blog.youkuaiyun.com/judyfun/article/details/45974223
Spring AOP的代理模式详解
本文介绍了静态代理和两种动态代理(JDK动态代理与Cglib)的概念及实现方式,通过具体示例展示了如何利用代理模式进行面向切面编程(AOP),实现业务逻辑与辅助操作的解耦。
373

被折叠的 条评论
为什么被折叠?



