代理,顾名思义:就是中间人。举个例子:现在满大街都是移动代理店。假如你去办卡,就可以通过他们完成,还可以在他们店内购买手机。但是你想要销卡,就要去移动营业厅。代理店拥有移动的部分功能,并且还有自己扩展的业务。
java代理分为两种:静态代理和动态代理。
先来说说静态代理:就是委托类和代理类实现同一个接口,然后通过代理类的对象来执行委托类的方法。
具体代码如下:
接口:
package com.mec.about_staticProxy;
public interface IUserDao {
void setNum();
}
目标对象:
package com.mec.about_staticProxy;
public class UserDao implements IUserDao{
@Override
public void setNum() {
System.out.println("这是setNum方法");
}
}
代理對象:
package com.mec.about_staticProxy;
public class UserDaoProxy implements IUserDao{
private UserDao userDao;
public UserDaoProxy(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void setNum() {
System.out.println("开始执行SetNum()方法");
userDao.setNum();
System.out.println("执行SetNum()方法结束");
}
}
测试:
package com.mec.about_staticProxy;
public class Demo {
public static void main(String[] args) {
UserDaoProxy userDaoProxy = new UserDaoProxy(new UserDao());
userDaoProxy.setNum();
}
}
输出如下:
开始执行SetNum()方法
这是setNum方法
执行SetNum()方法结束
优点:可以实现在不修改目标对象的基础上,对目标对象的功能进行扩展。
缺点:由于代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
再来看动态代理,动态代理分为jdk动态代理和cglib动态代理。
jdk动态代理通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现代理类:
package com.mec.about_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class YcProxy {
public YcProxy() {
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Object object) {
Class<?> klass = object.getClass();
return (T) Proxy.newProxyInstance(klass.getClassLoader(), klass.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("调用Method方法" + method.getName() + "()前... ...");
try {
result = method.invoke(object, args);
System.out.println("调用Method方法" + method.getName() + "()后... ...");
} catch (Exception e) {
System.out.println("调用Method" + method.getName() + "()方法发生异常!!!");
throw e;
}
return result;
}
});
}
}
编写一个接口,规定要实现的方法:
package com.mec.about_proxy.classes;
public interface IUserModel {
void setName(String name);
String getName(String worker);
}
委托类:
package com.mec.about_proxy.classes;
public class UserDao implements IUserDao{
@Override
public UserModel getUserById(String id) {
UserModel user = new UserModel();
user.setName(id);
return user;
}
}
测试:
package com.mec.about_proxy;
import com.mec.about_proxy.classes.IUserModel;
import com.mec.about_proxy.classes.UserModel;
public class Demo {
public static void main(String[] args) {
IUserModel object = new YcProxy().getProxy(new UserModel());
object.setName("susan");
System.out.println(object.getName("0001"));
}
}
输出结果如下:
调用Method方法setName()前... ...
调用Method方法setName()后... ...
调用Method方法getName()前... ...
调用Method方法getName()后... ...
susan
可以在代理中增加额外业务:比如日志
再来看看cglib动态代理:
此代理通过【code generation library】实现:
package com.mec.about_cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGlibProxy {
private IntercepterAdapter intercepter;
public CGlibProxy() {
}
public void addIntercepter(IntercepterAdapter intercepterAdapter) {
this.intercepter = intercepterAdapter;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<?> klass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
Object result = null;
if (intercepter.before(object, args) == false) {
return false;
}
try {
result = methodProxy.invokeSuper(object, args);
intercepter.after(object, result);
} catch (Exception e) {
intercepter.occurExcption(object, e);
}
return result;
}
});
return(T)enhancer.create();
}
}
定义接口,规定要实现的方法:
package com.mec.about_cglib;
public interface IIntercepter {
boolean before(Object object, Object[] args);
void after(Object object, Object result);
void occurExcption(Object object, Throwable e);
}
编写一个接口的Adapter:
package com.mec.about_cglib;
import java.lang.reflect.Method;
public class IntercepterAdapter implements IIntercepter{
private Method method;
public IntercepterAdapter(Method method) {
this.method = method;
}
public Method getMethod() {
return method;
}
@Override
public boolean before(Object object, Object[] args) {
return true;
}
@Override
public void after(Object object, Object result) {
}
@Override
public void occurExcption(Object object, Throwable e) {
}
}
测试如下:
package com.mec.about_proxy;
import java.lang.reflect.Method;
import com.mec.about_cglib.CGlibProxy;
import com.mec.about_cglib.IntercepterAdapter;
import com.mec.about_proxy.classes.NormalClass;
public class Demo {
public static void main(String[] args) {
Method method;
try {
method = NormalClass.class.getMethod("normalAction", new Class<?>[] { String.class });
new CGlibProxy().addIntercepter(new IntercepterAdapter(method) {
@Override
public boolean before(Object object, Object[] args) {
System.out.println("在方法" + method.getName() + "()执行之前……");
return true;
}
@Override
public void after(Object object, Object result) {
System.out.println("在方法" + method.getName() + "()执行之后……");
}
@Override
public void occurExcption(Object object, Throwable e) {
System.out.println("在方法" + method.getName() + "()执行时异常……");
}
});
NormalClass normalClass = new CGlibProxy().getProxy(NormalClass.class);
normalClass.fun();
normalClass.setNum(88);
normalClass.normalAction("8888");
} catch (NoSuchMethodException | SecurityException e1) {
e1.printStackTrace();
}
}
}
输出结果如下
这是一个final方法!!!
在方法normalAction()执行之前……
在方法normalAction()执行之后……
在方法normalAction()执行之前……
8888 : 88
在方法normalAction()执行之后……
jdk和cglib动态代理实现的区别
1、jdk动态代理生成的代理类和委托类实现了相同的接口;
2、cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被final关键字修饰的方法;
3、jdk采用反射机制调用委托类的方法,cglib采用类似索引的方式直接调用委托类方法(FastClass);