代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,
代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供
特定的服务。
有了解动态代理你必须先了解java的反射机制(点击查看)
1.Java动态代理有两种实现:
1. JDK动态代理(委托类必须接口实现,代理类实现InvocationHandler接口,springAop默认的实现方式)
2. Cglib动态代理(委托类可以不实现接口,也可以实现接口,代理类实现MethodInterceptor,spring的bean在没实现接口时使用的Cglib实现AOP),使用Cglib提供的过滤器CallbackFilter 可以明确表明,被代理的类(InfoManager)中不同的方法,被哪个拦截器(interceptor,即代理类)拦截。
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。
2.JDK动态代理
//接口
public interface Count {
public void CountAll();
public void AddMethod();
}
//实现 委托类
public class CountImpl implements Count{
@Override
public void CountAll() {
try{
Thread.sleep(2000);
System.out.println("count start...");
}catch(Exception e){
e.printStackTrace();
}
}
@Override
public void AddMethod() {
System.out.println("AddMethod start...");
}
}
//代理类 实现 InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JDKProxy implements InvocationHandler{
private Count count;
public JDKProxy(Count count){
this.count = count;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("begin...");
method.invoke(count, args);
System.out.println("end...");
return null;
}
}
//工厂
import java.lang.reflect.Proxy;
public class CountFactory {
public static Count getProxyInstance(Count count){
return (Count)Proxy.newProxyInstance(count.getClass().getClassLoader(), count.getClass().getInterfaces(), new JDKProxy(count));
}
}
//客户端
public class Client {
public static void main(String[] arg){
Count count = new CountImpl();
Count countProxy = CountFactory.getProxyInstance(count);
countProxy.CountAll();
count.CountAll();
}
}
@输出:begin...
count start...
end...
count start...
2.Cglib动态代理
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。最流行的OR Mapping工具hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实现的)
@代码:
//委托类
public class InfoManager {
public void query() {
System.out.println("query");
}
public void delete() {
System.out.println("delete");
}
}
//代理类 实现
MethodInterceptor
public class AuthProxy implements MethodInterceptor{
String name;
public AuthProxy(String name){
this.name = name;
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
if(this.name.equals("dxswzj")){//当dxswzj时才可以操作
//对方法进行过滤
if(arg1.getName().equals("delete")){
System.out.println("you can't do delete!");
}else{
System.out.println("方法前置代理");
arg3.invokeSuper(arg0, arg2);
System.out.println("方法后置代理");
}
}else{
System.out.println("you can't do anything!");
}
return null;
}
}
//工厂类
public class InfoManagerFactory {
public static InfoManager getInstance(AuthProxy proxy){
Enhancer enhancer = new Enhancer();
//设置需要创建子类的类
enhancer.setSuperclass(InfoManager.class);
enhancer.setCallback(proxy);
//通过字节码技术动态创建子类实例
return (InfoManager)enhancer.create();
}
}
//客户端
public static void main(String[] arg){
Client c = new Client();
AuthProxy proxy = new AuthProxy("dxswzj");
InfoManager manager = InfoManagerFactory.getInstance(proxy);
manager.delete();
manager.query();
}
@输出:you can't do delete!
方法前置代理
query
方法后置代理