- 定义 为其他对象提供一种代理以控制对这个对象的访问。
- 本质 控制对象访问
- 实例 以歌星为例:歌星的合作过程 面谈,签合同,唱歌,收尾款 其实有些步骤不需要明星亲自去做 比如面谈,签合同,收尾款。明星只需要唱歌即可。其他交由经纪人去做!
静态代理实现:
Star 歌星
/**
* 歌星
* @author lijun
* @since 2018-03-12 14:12
*/
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 唱歌
*/
void sing();
/**
* 收尾款
*/
void collectMoney();
}
JackyCheung 具体的歌星张学友
/**
* 张学友
* @author lijun
* @since 2018-03-12 14:14
*/
public class JackyCheung implements Star {
/**
* 面谈
*/
@Override
public void confer() {
}
/**
* 签合同
*/
@Override
public void signContract() {
}
/**
* 唱歌
*/
@Override
public void sing() {
System.out.println("张学友唱歌。。。。");
}
/**
* 收尾款
*/
@Override
public void collectMoney() {
}
}
经纪人
/**
* 经纪人
* @author lijun
* @since 2018-03-12 14:18
*/
public class Agent implements Star{
private Star star;
public Agent(Star star) {
this.star = star;
}
/**
* 面谈
*/
@Override
public void confer() {
System.out.println("经纪人代表面谈!");
}
/**
* 签合同
*/
@Override
public void signContract() {
System.out.println("经纪人代表签合同!");
}
/**
* 唱歌
*/
@Override
public void sing() {
star.sing();
}
/**
* 收尾款
*/
@Override
public void collectMoney() {
System.out.println("经纪人代表收尾款!");
}
}
只有唱歌 需要具体的明星来做!其他都交由经纪人来做!
调用:
public void sing(){
Star star = new JackyCheung();
Agent agent = new Agent(star);
agent.confer();
agent.signContract();
agent.sing();
agent.collectMoney();
}
输出:
经纪人代表面谈!
经纪人代表签合同!
张学友唱歌。。。。
经纪人代表收尾款!
用JDK动态代理实现
/**
* 动态代理的经纪人
* @author lijun
* @since 2018-03-12 14:57
*/
public class AgentDynamic implements InvocationHandler{
private Star star;
/** 获取代理对象
* @param target star
* @return Object
*/
public Object getInstance(Star target){
this.star = target;
Class<? extends Star> aClass = target.getClass();
return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
String name = method.getName();
if (name.equals("sing")){
System.out.println("经纪人代表面谈!");
System.out.println("经纪人代表签合同!");
object = method.invoke(star, args);
System.out.println("经纪人代表收尾款!");
}
return object;
}
}
调用:
public void singDynamic(){
AgentDynamic agentDynamic = new AgentDynamic();
Star star = (Star)agentDynamic.getInstance(new JackyCheung());
System.out.println(star.getClass());
star.sing();
}
输出:
class com.sun.proxy.$Proxy4
经纪人代表面谈!
经纪人代表签合同!
张学友唱歌。。。。
经纪人代表收尾款!
上面看到生成的代理类名字为$Proxy4 里面的类容是什么呢!我可以把类容写到磁盘!
修改测试方法把类写到磁盘!
public void singDynamic(){
AgentDynamic agentDynamic = new AgentDynamic();
Star star = (Star)agentDynamic.getInstance(new JackyCheung());
System.out.println(star.getClass());
star.sing();
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy4", new Class[]{Star.class});
try {
FileOutputStream fileOutputStream = new FileOutputStream("E:\$Proxy4.class");
fileOutputStream.write(bytes);
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
反编译 $Proxy4.class 得到:
import com.junli.staticed.Star;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy4 extends Proxy implements Star {
private static Method m1;
private static Method m4;
private static Method m6;
private static Method m2;
private static Method m3;
private static Method m5;
private static Method m0;
public $Proxy4(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void signContract() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void collectMoney() throws {
try {
super.h.invoke(this, m6, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void confer() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void sing() throws {
try {
super.h.invoke(this, m5, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com.junli.staticed.Star").getMethod("signContract");
m6 = Class.forName("com.junli.staticed.Star").getMethod("collectMoney");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.junli.staticed.Star").getMethod("confer");
m5 = Class.forName("com.junli.staticed.Star").getMethod("sing");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可以看出生成类的过程,可以看到JDK动态代理的原理:
1、拿到被代理对象的引用,并且获取到它的所有的接口,反射获取
2、JDK Proxy类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口
3、动态生成Java代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)
4、编译新生成的Java代码.class
5、再重新加载到JVM中运行
知道原理了我们就可以自己实现JDK动态代理的功能!其实关键就是Proxy代理类的实现!实现如下:
自定义的动态代理实现
LIInvocationHandler 自定义的InvocationHandler
/**
* 自定义的InvocationHandler
* @author lijun
* @since 2018-03-12 17:02
*/
public interface LIInvocationHandler {
/**
*
* @param proxy proxy
* @param method method
* @param args args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
LIClassLoader 自定义类加载器
/**
*
* @author lijun
* @since 2018-03-12 17:59
*/
public class LIClassLoader extends ClassLoader{
private File classPathFile;
public LIClassLoader(){
String classPath = LIClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
{
String className = LIClassLoader.class.getPackage().getName() + "." + name;
if(classPathFile != null){
File classFile = new File(classPathFile,name.replaceAll("\.","/") + ".class");
if(classFile.exists()){
FileInputStream in = null;
ByteArrayOutputStream out = null;
try{
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte [] buff = new byte[1024];
int len;
while ((len = in.read(buff)) != -1){
out.write(buff,0,len);
}
return defineClass(className,out.toByteArray(),0,out.size());
}catch (Exception e){
e.printStackTrace();
}finally {
if(null != in){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}
}
LIProxy 自定义的代理类
/**
* 自己的代理类
* @author lijun
* @since 2018-03-12 17:58
*/
public class LIProxy {
public static final String ln = "
";
public static Object newProxyInstance(LIClassLoader classLoader, Class<?>[] interfaces, LIInvocationHandler h) {
try {
//1、动态生成源代码.java文件
String src = generateSrc(interfaces);
//2、Java文件输出磁盘
String filePath = LIProxy.class.getResource("").getPath();
System.out.println(filePath);
File f = new File(filePath + "$Proxy4.java");
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
//3、把生成的.java文件编译成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manage = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manage.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manage, null, null, null, iterable);
task.call();
manage.close();
//4、编译生成的.class文件加载到JVM中来
Class proxyClass = classLoader.findClass("$Proxy4");
Constructor c = proxyClass.getConstructor(LIInvocationHandler.class);
//f.delete();
//5、返回字节码重组以后的新的代理对象
return c.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class<?>[] interfaces){
StringBuffer sb = new StringBuffer();
sb.append("package com.junli.custom;" + ln);
sb.append("import com.junli.staticed.Star;" + ln);
sb.append("import java.lang.reflect.Method;" + ln);
sb.append("public class $Proxy4 implements " + interfaces[0].getName() + "{" + ln);
sb.append("LIInvocationHandler h;" + ln);
sb.append("public $Proxy4(LIInvocationHandler h) { " + ln);
sb.append("this.h = h;");
sb.append("}" + ln);
for (Method m : interfaces[0].getMethods()){
sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
sb.append("try{" + ln);
sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod("" + m.getName() + "",new Class[]{});" + ln);
sb.append("this.h.invoke(this,m,null);" + ln);
sb.append("}catch(Throwable e){" + ln);
sb.append("e.printStackTrace();" + ln);
sb.append("}");
sb.append("}");
}
sb.append("}" + ln);
return sb.toString();
}
}
AgentCustomDynamic 自定义 动态代理的经纪人
/**
*自定义 动态代理的经纪人
* @author lijun
* @since 2018-03-12 14:57
*/
public class AgentCustomDynamic implements LIInvocationHandler{
private Star star;
/** 获取代理对象
* @param target star
* @return Object
*/
public Object getInstance(Star target){
this.star = target;
Class<?> aClass = target.getClass();
return LIProxy.newProxyInstance(new LIClassLoader(),aClass.getInterfaces(),this);
}
/**
* 参数:
*proxy 被代理的对象
*method 被代理对象的方法
*args 方法的参数
* 返回:
*Object 方法返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
String name = method.getName();
if (name.equals("sing")){
System.out.println("经纪人代表面谈!");
System.out.println("经纪人代表签合同!");
object = method.invoke(star, args);
System.out.println("经纪人代表收尾款!");
}
return object;
}
}
调用
@Test
public void singCustom() {
AgentCustomDynamic agentCustomDynamic = new AgentCustomDynamic();
Star star = (Star)agentCustomDynamic.getInstance(new JackyCheung());
System.out.println(star.getClass());
star.sing();
}
输出
class com.junli.custom.$Proxy4
经纪人代表面谈!
经纪人代表签合同!
张学友唱歌。。。。
经纪人代表收尾款!
实现了动态代理的功能!
Cglib 实现
/**
* Cglib动态代理实现
* @author lijun
* @since 2018-03-12 16:11
*/
public class AgentCglib implements MethodInterceptor {
/**
*
* @param clazz clazz 被代理类的具体实现类
* @return Object
*/
public Object getInstance(Class<?> clazz){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 拦截所有目标类方法的调用
* 参数:
* obj目标实例对象
*method 目标方法的反射对象
* args方法的参数
* proxy代理类的实例
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object object = null;
String name = method.getName();
if (name.equals("sing")){
System.out.println("经纪人代表面谈!");
System.out.println("经纪人代表签合同!");
object = methodProxy.invokeSuper(o, objects);
System.out.println("经纪人代表收尾款!");
}
return object;
}
}
调用
@Test
public void singCglib() {
AgentCglib agentCglib = new AgentCglib();
Star star = (Star)agentCglib.getInstance(JackyCheung.class);
System.out.println(star.getClass());
star.sing();
}
@Test
public void singCglib() {
AgentCglib agentCglib = new AgentCglib();
Star star = (Star)agentCglib.getInstance(JackyCheung.class);
System.out.println(star.getClass());
star.sing();
}
输出:
class com.junli.staticed.JackyCheung$$EnhancerByCGLIB$$89c7b75a
经纪人代表面谈!
经纪人代表签合同!
张学友唱歌。。。。
经纪人代表收尾款!
代理模式学习完毕!