//要找对象的男孩
public class Man implements Person{
public void findLove(){
System.out.println("儿子要求:肤白貌美大长腿");
}
}
//媒婆
public class Matchmaker implements Person {
private Man man;
public Matchmaker(Man man){
this.man = man;
}
public void findLove(){
System.out.println("媒婆整理手中资源");
this.man.findLove();
System.out.println("按照男孩要求物色");
System.out.println("物色到合适的后--善后处理");
}
}
//测试类
public class TestDemo {
public static void main(String[] args) {
Matchmaker matchmaker = new Matchmaker(new Man());
matchmaker.findLove();
}
}
//人员信息
public class PersonInfo {
private String name;
private int age;
}
//mapper层
public interface PersonInfoMapper {
Integer insertPerson(PersonInfo personInfo);
}
//service实现
public class PersonInfoServiceImpl implements PersonInfoService {
PersonInfoMapper personInfoMapper;
public Integer insertPerson(PersonInfo personInfo) {
//新增逻辑
return 1;
}
}
//切换数据源工具类
public class DynamicDataSourceEntry {
// 默认数据源
public final static String DEFAULT_SOURCE = "默认数据源name";
//当前类为工具类,必须考虑并发,ThreadLocal可以实现线程之间的资源隔离
// 与synchronized【实现线程之间的资源共享】关键字正好相反,不了解者可自行百度
private final static ThreadLocal<String> local = new ThreadLocal<String>();
private DynamicDataSourceEntry(){
}
//清空数据源
public static void clear() {
local.remove();
}
//获取当前数据源的名字
public static String get() {
return local.get();
}
//还原默认数据源
public static void restore() {
local.set(DEFAULT_SOURCE);
}
//根据省份设置数据源
public static void set(String province) {
local.set("DB_" + province);
}
}
//相当于媒婆
public class ChangeDataSourceStaticProxy {
//相当于要找对象的男孩
private PersonInfoService personInfoService;
public ChangeDataSourceStaticProxy(PersonInfoService personInfoService) {
this.personInfoService = personInfoService;
}
public Integer insertPersonInfo(PersonInfo personInfo){
//根据当前人所在省份的信息,生成数据源名称 例如:dbName = DB_ + 省份名称
//向ThreadLocal中写入当前要操作的数据源名称
DynamicDataSourceEntry.set("当前要操作的数据源名称dbName");
//切换数据源代码
//执行插入操作
personInfoService.insertPerson(personInfo);
//......此处省略500个方法【在这500个方法中如需获取当前数据源的名称进行操作即可调用DynamicDataSourceEntry.get();】
return 1;
}
}
public class XiaoGaoPerson implements Person {
public boolean findLove() {
System.out.println("小高:哪那么多要求,女的就行");
return false;
}
}
public class JDKProxy implements InvocationHandler {
//被代理对象
private Object target;
public Object getInstance(Object target){
this.target = target;
Class<?> targetClass = target.getClass();
return Proxy.newProxyInstance(targetClass.getClassLoader(),targetClass.getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforMethod();
Object proxyTarget = method.invoke(this.target, args);
afterMethod();
return proxyTarget;
}
private void beforMethod() {
System.out.println("媒婆:来说说条件");
}
private void afterMethod() {
System.out.println("媒婆:......无语");
System.out.println("媒婆:我给你看看");
}
}
public class TestJDKProxy {
public static void main(String[] args) {
Person person = (Person)new JDKProxy().getInstance(new XiaoGaoPerson());
person.findLove();
}
}
有没有感觉很神奇的样子呢?JDK使用的是字节码重组技术,通过生成对象类代理原始对象,并通过调用原始对象的方法。JDK 中有一个规范,在 ClassPath 下只要是$开头的 class 文件一般都是自动生成的。反编译工具
详细步骤为:
执行如下代码,获取代理后的class文件:
public class ObtainJDKProxyAfterClass {
public static void main(String[] args) {
Person person = (Person)new JDKProxy().getInstance(new XiaoGaoPerson());
person.findLove();
byte [] bytes = ProxyGenerator.generateProxyClass("$ProxyGao",new Class[]{Person.class});
FileOutputStream os = null;
try {
os = new FileOutputStream("D://$ProxyGao.class");
os.write(bytes);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这不,我这有,你运行你也有,大家有才是真的有
下面是反编译后的代码:
public final class $ProxyGao extends Proxy
implements Person
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $ProxyGao()
throws
{
super(paramInvocationHandler);
}
public final boolean equals()
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final boolean findLove()
throws
{
try
{
return ((Boolean)this.h.invoke(this, m3, null)).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return ((String)this.h.invoke(this, m2, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.gupaoedu.vip.pattern.proxy.staticproxy.Person").getMethod("findLove", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
通过分析代码我们发现【下面代码取自反编译后的代码】:
public final class $ProxyGao extends Proxy
implements Person
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.gupaoedu.vip.pattern.proxy.staticproxy.Person").getMethod("findLove", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
public final boolean findLove()
throws
{
try
{
return ((Boolean)this.h.invoke(this, m3, null)).booleanValue();//通过反射调用
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public class XiaoGaoPerson {
public boolean findLove() {
System.out.println("小高:哪那么多要求,女的就行");
return false;
}
}
public class CGLibProxy implements MethodInterceptor{
private Object target;
public Object getInstance(Object source){
target = source;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
//进行业务增强
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
beforMethod();
//此处需要调用被代理的方法
//使用方法1或者方法2均可,但是方法3会造成死循环
//原因在于,方法3调用的是代理之后的方法,相当于在代理之后的方法中再调用代理之后的方法,然后你就会看到它:StackOverflowError
Object obj = methodProxy.invoke(this.target, objects);//方法1
//Object obj = methodProxy.invokeSuper(o, objects); //方法2
//Object obj = methodProxy.invoke(o, objects); //方法3
afterMethod();
return obj;
}
private void beforMethod() {
System.out.println("媒婆:来说说条件");
}
private void afterMethod() {
System.out.println("媒婆:......无语");
System.out.println("媒婆:我给你看看");
}
}
public class CGLibTest {
public static void main(String[] args) throws Exception {
XiaoGaoPerson person = (XiaoGaoPerson)new CGLibProxy().getInstance(XiaoGaoPerson.class);
person.findLove();
}
}
public class CGLibTest {
public static void main(String[] args) throws Exception {
//利用cglib的代理类可以将内存中的class文件写入到本地磁盘
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D://cglib");
XiaoGaoPerson person = (XiaoGaoPerson)new CGLibProxy().getInstance(XiaoGaoPerson.class);
person.findLove();
}
}
package proxy.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class fd16c28d extends XiaoGaoPerson
implements Factory
{
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$findLove$0$Method;
private static final MethodProxy CGLIB$findLove$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1()
{
Class localClass2;
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class localClass1 = Class.forName("proxy.cglib.XiaoGaoPerson$$EnhancerByCGLIB$$fd16c28d");
Method[] tmp83_80 = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = tmp83_80[0];
CGLIB$equals$1$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
Method[] tmp103_83 = tmp83_80;
CGLIB$toString$2$Method = tmp103_83[1];
CGLIB$toString$2$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
Method[] tmp123_103 = tmp103_83;
CGLIB$hashCode$3$Method = tmp123_103[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$3");
Method[] tmp143_123 = tmp123_103;
CGLIB$clone$4$Method = tmp143_123[3];
CGLIB$clone$4$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
tmp143_123;
Method[] tmp191_188 = ReflectUtils.findMethods(new String[] { "findLove", "()Z" }, (localClass2 = Class.forName("proxy.cglib.XiaoGaoPerson")).getDeclaredMethods());
CGLIB$findLove$0$Method = tmp191_188[0];
CGLIB$findLove$0$Proxy = MethodProxy.create(localClass2, localClass1, "()Z", "findLove", "CGLIB$findLove$0");
tmp191_188;
}
final boolean CGLIB$findLove$0()
{
return super.findLove();
}
public final boolean findLove()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 == null)
break label52;
label45: label52: if (tmp17_14.intercept(this, CGLIB$findLove$0$Method, CGLIB$emptyArgs, CGLIB$findLove$0$Proxy) != null)
break label45;
}
final boolean CGLIB$equals$1()
{
return super.equals(paramObject);
}
public final boolean equals()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 == null)
break label57;
label50: label57: if (tmp17_14.intercept(this, CGLIB$equals$1$Method, new Object[] { paramObject }, CGLIB$equals$1$Proxy) != null)
break label50;
}
final String CGLIB$toString$2()
{
return super.toString();
}
public final String toString()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
return ((String)tmp17_14.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy));
return super.toString();
}
final int CGLIB$hashCode$3()
{
return super.hashCode();
}
public final int hashCode()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 == null)
break label52;
label45: label52: if (tmp17_14.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy) != null)
break label45;
}
final Object CGLIB$clone$4()
throws CloneNotSupportedException
{
return super.clone();
}
protected final Object clone()
throws CloneNotSupportedException
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null)
return tmp17_14.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy);
return super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature)
{
String tmp4_1 = paramSignature.toString();
switch (tmp4_1.hashCode())
{
case -508378822:
if (!(tmp4_1.equals("clone()Ljava/lang/Object;")))
break label121;
label121: return CGLIB$clone$4$Proxy;
case 1192015566:
case 1826985398:
case 1913648695:
case 1984935277:
}
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
{
CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
{
CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
}
private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
{
fd16c28d localfd16c28d = (fd16c28d)paramObject;
if (localfd16c28d.CGLIB$BOUND)
break label52;
localfd16c28d.CGLIB$BOUND = true;
Object tmp23_20 = CGLIB$THREAD_CALLBACKS.get();
if (tmp23_20 != null)
break label39;
tmp23_20;
Callback[] tmp31_28 = CGLIB$STATIC_CALLBACKS;
if (tmp31_28 != null)
break label39;
tmp31_28;
label39: label52: break label52:
}
public Object newInstance()
{
CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
CGLIB$SET_THREAD_CALLBACKS(null);
return new fd16c28d();
}
public Object newInstance()
{
CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
CGLIB$SET_THREAD_CALLBACKS(null);
return new fd16c28d();
}
public Object newInstance(, Object[] paramArrayOfObject, Callback[] paramArrayOfCallback)
{
CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
Class[] tmp9_8 = paramArrayOfClass;
switch (tmp9_8.length)
{
case 0:
tmp9_8;
break;
default:
new fd16c28d();
throw new IllegalArgumentException("Constructor not found");
}
CGLIB$SET_THREAD_CALLBACKS(null);
}
public Callback getCallback()
{
CGLIB$BIND_CALLBACKS(this);
switch (paramInt)
{
case 0:
}
return null;
}
public void setCallback(, Callback paramCallback)
{
switch (paramInt)
{
case 0:
this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramCallback);
}
}
public Callback[] getCallbacks()
{
CGLIB$BIND_CALLBACKS(this);
return { this.CGLIB$CALLBACK_0 };
}
public void setCallbacks()
{
this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramArrayOfCallback[0]);
}
static
{
CGLIB$STATICHOOK1();
}
}
通过分析代码我们发现【下面代码取自反编译后的代码】:
public class fd16c28d extends XiaoGaoPerson
implements Factory
tmp17_14.intercept()
调用代理类CGLibProxy中的intercept()方法
final boolean CGLIB$findLove$0()
{
return super.findLove();
}
public final boolean findLove()
{
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null)
{
tmp4_1;
CGLIB$BIND_CALLBACKS(this);
}
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 == null)
break label52;
label45: label52: if (tmp17_14.intercept(this, CGLIB$findLove$0$Method, CGLIB$emptyArgs, CGLIB$findLove$0$Proxy) != null)
break label45;
}
优点:
▄█▀█●各位同仁,如果我的代码对你有帮助,请给我一个赞吧,为了下次方便找到,也可关注加收藏呀
如果有什么意见或建议,也可留言区讨论