一、观察者模型

      观察者模式,就是生产者消费者模式。下面我们来简单的建立一个生产者消费者模型。

1、建立生产者类

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private List<ObServer> list;

    public ProductServer(){
        list=new ArrayList<>();
    }

    public void  sendMessage(Object message){
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                obServer.receiverMessage(message);
            }
        }
    }

    public void addObServer(ObServer obServer) {
        list.add(obServer);
    }

}

2、建立生产者对应的消费者(观察者)接口

package com.dgw.hostel.observer;

/**
 * 观察者,接收消息
 */
public interface ObServer {

    public void receiverMessage(Object message);
}

3、让具体需要接受消息的spring bean类,去实现该接口。

package com.dgw.hostel.observer;

import lombok.Data;
import org.springframework.stereotype.Component;

@Component
public class ObServerImpl implements ObServer {

    @Override
    public void receiverMessage(Object message) {
        System.out.println("观察者1"+message);
    }
}


package com.dgw.hostel.observer;

import org.springframework.stereotype.Component;

@Component
public class ReceiverMessage implements ObServer{

    @Override
    public void receiverMessage(Object message) {
        System.out.println("观察者2:"+message);
    }
}

4、在具体的项目中取使用,生产消息

package com.dgw.hostel;

import com.dgw.hostel.observer.ObServerBuider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HostelApplicationTests {

	@Test
	public void contextLoads() {
		ObServerBuider.buider().sendMessage("发送消息测试");
	}

}

5、测试结果

观察者1发送消息测试
观察者2:发送消息测试

 

二、存在问题

1、假设我要建立另外一个消息主题,会员推送:只给会员推送非会员不进行推送,如何扩展?

2、能否进一步让消费者变得更简洁,进一步解耦让消费者不用关心有观察者这个东西,只用关心某个消息主题即可?

 

三、解决存在问题

      针对第一个问题,我们采用了建造者模式,为某一个主题单独创建一个建造者方法。来构建这一个主题的生产者-消费者。这个也复合开闭原则。

如果有另外一主题的消息需要发送时,在生产者和消费者里面加特定方法来发送这一主题的消息。

1、观察者改造

package com.dgw.hostel.observer;

/**
 * 观察者,接收消息
 */
public interface ObServer {

    public void receiverMessage(Object message);

    //会员充值,发送消息
    public void sendMessage(Object message);
}

 

2、生产者改造

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private List<ObServer> list;

    public ProductServer(){
        list=new ArrayList<>();
    }

    //接收消息测试
    public void  receiverMessage(Object message){
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                obServer.receiverMessage(message);
            }
        }
    }

    //发送消息测试
    public void  sendMessage(Object message){
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                obServer.sendMessage(message);
            }
        }
    }

    public void addObServer(ObServer obServer) {
        list.add(obServer);
    }

}

3、spring bean具体消费者类改造

package com.dgw.hostel.observer;

import lombok.Data;
import org.springframework.stereotype.Component;

@Component
public class ObServerImpl implements ObServer {

    @Override
    public void receiverMessage(Object message) {
        System.out.println("观察者1"+message);
    }

    @Override
    public void sendMessage(Object message) {
        System.out.println("观察者1"+message);
    }

}


package com.dgw.hostel.observer;

import org.springframework.stereotype.Component;

@Component
public class ReceiverMessage implements ObServer{

    @Override
    public void receiverMessage(Object message) {
        System.out.println("观察者2:"+message);
    }

    @Override
    public void sendMessage(Object message) {
        System.out.println("观察者2:"+message);
    }

}

       虽然复合开闭原则,但是我们发现,我们已发出消息,所有观察者的子类都必须去实现观察者接口的所有方法,而另外一个主题的方法是我们不需要的。这个迪米特法则不复合。

      我们继续改造,为生产者添加消息类别:区分消息的主题。

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private String msgType;

    private List<ObServer> list;

    public ProductServer(){
        list=new ArrayList<>();
    }
    public ProductServer(String msgType){
        list=new ArrayList<>();
        this.msgType=msgType;
    }

    //接收消息测试
    public void  receiverMessage(Object message){
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                obServer.receiverMessage(message);
            }
        }
    }

    //发送消息测试
    public void  sendMessage(Object message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                try {
                    MessageListener sendMessage = obServer.getClass().getMethod("sendMessage", Object.class).getAnnotation(MessageListener.class);
                    if (sendMessage!=null && sendMessage.value().equals(this.msgType)) {
                        obServer.sendMessage(message);
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void addObServer(ObServer obServer) {
        list.add(obServer);
    }

}

        在具体的观察者(消费者)方法上添加 @MessageListener 注解,在生产者发送消息时,首先获取@MessageListener注解的值。判断注解的值是否是该生产者的消息主题,如果是,则发送消息,不是则 不发送。

package com.dgw.hostel.observer;

import lombok.Data;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class ObServerImpl implements ObServer {

    @Override
    public void receiverMessage(Object message) {
        System.out.println("观察者1"+message);
    }

    @MessageListener(value = "sendMessage")
    @Override
    public void sendMessage(Object message) {
        System.out.println("观察者1"+message);
    }

}

    添加过后之后,测试发现,只有加了@MessageListener注解,并且值为sendMessage时,才会接收到该消息。

上面获取注解的时候我们依赖了消费者的方法名,我们继续改造,使其不依赖该方法名获取注解。

//发送消息测试
    public void  sendMessage(Object message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                try {
                    Class<? extends ObServer> clazz = obServer.getClass();
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
                            obServer.sendMessage(message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

 

我们再来看,加入我们具体的实现类里面有两个方法都有@MessageListener注解,可现在调用还是依赖以ObServer接口的sendMessage()方法,我想一个具体的类里面定义两个带@MessageListener注解的方法。怎么实现呢?再来改造通过反射调用,同时删除观察者接口中的方法

//发送消息测试
    public void  sendMessage(Object message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObServer obServer : list) {
                try {
                    Class<? extends ObServer> clazz = obServer.getClass();
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
//                            obServer.sendMessage(message);
                            method.invoke(obServer,message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }




package com.dgw.hostel.observer;

/**
 * 观察者,接收消息
 */
public interface ObServer {

    //会员充值,发送消息
//    public void sendMessage(Object message);
}

    再来看,我们现在生产者调用,消费者已经不依赖消费者中的方法名称。也实现了消息分组,可我们实现了观察者接口。那这个接口看似有点多余,我们继续进行改造。直接从spring 容器中获取bean,然后在调用bean中带有该注解的方法。

1、建造者改造,通过某个注解获取beans
package com.dgw.hostel.observer;

import com.dgw.hostel.util.SpringContextUtil;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 用建造者模式,创建观察者对象
 */
public class ObServerBuider {


    /**
     * 建造者方法
     */
    public static ProductServer buider(String msgType) {
        //发送者
        ProductServer productServer = new ProductServer(msgType);

        //获取观察者
        Map<String, Object> beans = SpringContextUtil.getBeansWithAnnotation(MessageListener.class);
        Set<String> strings = beans.keySet();
        for (String key : strings) {
            Object object=beans.get(key);
            //将观察者添加到发送者集合中
            productServer.addObServer(object);
        }
        return productServer;
    }


}


2、生产者改造,将观察者直接提升为Object

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private String msgType;

    private List<Object> list;

    public ProductServer(){
        list=new ArrayList<>();
    }
    public ProductServer(String msgType){
        list=new ArrayList<>();
        this.msgType=msgType;
    }

    public void addObServer(Object object) {
        list.add(object);
    }

    //发送消息测试
    public void  sendMessage(Object message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (Object object : list) {
                try {
                    Class<?> clazz = object.getClass();
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
                            method.invoke(object,message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}


3、具体的消费者改造

package com.dgw.hostel.observer;

import lombok.Data;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
@MessageListener
public class ObServerImpl {

    @MessageListener(value = "sendMessage")
    public void sendMessage(Object message) {
        System.out.println("观察者1"+message);
    }

    @MessageListener(value = "sendMessage")
    public void sendMessage2(Object message) {
        System.out.println("sendMessage2观察者1"+message);
    }

    public void sendMessage3(Object message) {
        System.out.println("观察者1"+message);
    }
    @MessageListener(value = "love")
    public void sendMessage4(Object message) {
        System.out.println("观察者1---love==="+message);
    }
}
package com.dgw.hostel.observer;

import org.springframework.stereotype.Component;

@Component
@MessageListener
public class ReceiverMessage {

    @MessageListener(value = "love")
    public void sendMessage(Object message) {
        System.out.println("观察者2--love===:"+message);
    }

}


4、测试代码、发送两个不同的主题
package com.dgw.hostel;

import com.dgw.hostel.observer.ObServerBuider;
import com.dgw.hostel.observer.ProductServer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HostelApplicationTests {

	@Test
	public void contextLoads() {
		ObServerBuider.buider("sendMessage").sendMessage("发送消息测试");
		ObServerBuider.buider("love").sendMessage("鲁静恩");
	}

}

5、接收到的消息
观察者1发送消息测试
sendMessage2观察者1发送消息测试
观察者1---love===鲁静恩
观察者2--love===:鲁静恩

 

我们能不能直接不需要在类上加该注解,直接只用在方法上加注解就行呢?答案是行的,把spring ioc中的所有beans都取出来遍历一遍,但是效率太低了,我个人很不推荐,相比加个注解在类上,我个人还是觉得直接去实现某个接口调用该接口的方法,是个值得考虑的方案。

 

四、完整代码

package com.dgw.hostel.observer;

import org.springframework.stereotype.Indexed;

import java.lang.annotation.*;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface MessageListener {

    //消息主题
    String value() default "";

}
package com.dgw.hostel.observer;

/**
 * 观察者,接收消息
 */
public interface ObServer {

    //会员充值,发送消息
//    public void sendMessage(Object message);
}
package com.dgw.hostel.observer;

import com.dgw.hostel.util.SpringContextUtil;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 用建造者模式,创建观察者对象
 */
public class ObServerBuider {


    /**
     * 建造者方法
     */
    public static ProductServer buider(String msgType) {
        //发送者
        ProductServer productServer = new ProductServer(msgType);

        //获取观察者
        Map<String, Object> beans = SpringContextUtil.getBeansWithAnnotation(MessageListener.class);
        Set<String> strings = beans.keySet();
        for (String key : strings) {
            Object object=beans.get(key);
            //将观察者添加到发送者集合中
            productServer.addObServer(object);
        }
        return productServer;
    }


}
package com.dgw.hostel.observer;

import lombok.Data;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
@MessageListener
public class ObServerImpl {

    @MessageListener(value = "sendMessage")
    public void sendMessage(Object message) {
        System.out.println("观察者1"+message);
    }

    @MessageListener(value = "sendMessage")
    public void sendMessage2(Object message) {
        System.out.println("sendMessage2观察者1"+message);
    }

    public void sendMessage3(Object message) {
        System.out.println("观察者1"+message);
    }
    @MessageListener(value = "love")
    public void sendMessage4(Object message) {
        System.out.println("观察者1---love==="+message);
    }
}
package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private String msgType;

    private List<Object> list;

    public ProductServer(){
        list=new ArrayList<>();
    }
    public ProductServer(String msgType){
        list=new ArrayList<>();
        this.msgType=msgType;
    }

    public void addObServer(Object object) {
        list.add(object);
    }

    //发送消息测试
    public void  sendMessage(Object message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (Object object : list) {
                try {
                    Class<?> clazz = object.getClass();
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
                            method.invoke(object,message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
package com.dgw.hostel.observer;

import org.springframework.stereotype.Component;

@Component
@MessageListener
public class ReceiverMessage {

    @MessageListener(value = "love")
    public void sendMessage(Object message) {
        System.out.println("观察者2--love===:"+message);
    }

}
package com.dgw.hostel.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class SpringContextUtil implements ApplicationContextAware {
	
	// Spring应用上下文环境  
    private static ApplicationContext applicationContext;  
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringContextUtil.applicationContext=applicationContext;
	}
	
	//获取spring上下文
	public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }  
	
	//获取spring容器中的bean
	@SuppressWarnings("unchecked")
	public static <T>T getBean(String beanId) throws BeansException {  
        return (T)applicationContext.getBean(beanId);  
	}

	public static <T>T getBean(Class type) throws BeansException {
		return (T)applicationContext.getBean(type);
	}

	//从容器中获取所有接口的实现类
	public static <T> Map<String, T> getBeansOfType(Class type){
		return applicationContext.getBeansOfType(type);
	}

	//获取带有指定注解的beans
	public static Map<String, Object> getBeansWithAnnotation(Class type){
		return applicationContext.getBeansWithAnnotation(type);
	}

}
package com.dgw.hostel;

import com.dgw.hostel.observer.ObServerBuider;
import com.dgw.hostel.observer.ProductServer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HostelApplicationTests {

	@Test
	public void contextLoads() {
		ObServerBuider.buider("sendMessage").sendMessage("发送消息测试");
		ObServerBuider.buider("love").sendMessage("鲁静恩");
	}

}

 

 

    前面写这个例子的时候没有放到正式环境下使用过,今天放上去之后发现了,在service层存在aop代理对象时,代理对象的方法上取不到目标对象上的注解,所以对ProductService做了些修改。同时加入了按顺序发送消息。

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.support.AopUtils;


import java.lang.reflect.Method;
import java.util.*;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private String msgType;

    private List<Object> list;

    public ProductServer(String msgType){
        list=new ArrayList<>();
        this.msgType=msgType;
    }

    public void addObServer(Object object) {
        list.add(object);
    }

    //发送消息测试
    public void  sendMessage(Object ... message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (Object object : list) {
                try {
                    Class<?> clazz = getTargetClass(object);
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
                            object.getClass().getMethod(method.getName(),Object[].class).invoke(object,message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //发送消息,有顺序的执行
    public void  sendOrderMessage(Object ... message) {
        if (CollectionUtils.isNotEmpty(list)) {
            Set<Integer> orders = new TreeSet<>();
            Map<Integer,Object> targetObj=new HashMap<>();
            Map<Integer,Method> targetMethods=new HashMap<>();
            for (Object object : list) {
                try {
                    Class<?> clazz = getTargetClass(object);
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType) && messageListener.order() > -1) {
                            int order = messageListener.order();
                            orders.add(order);
                            targetObj.put(order,object);
                            targetMethods.put(order,method);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (orders.size() > 0) {
                for (Integer order : orders) {
                    try {
                        Object obj = targetObj.get(order);
                        Method method = targetMethods.get(order);
                        obj.getClass().getMethod(method.getName(),method.getParameterTypes()).invoke(obj,message);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }


    /**
     * 根据代理对象获取目标对象的类类型(处理有aop代理对象时,拿不到方法上的注解)
     * @param proxyObj
     * @return
     */
    private Class<?> getTargetClass(Object proxyObj){
        return AopUtils.isAopProxy(proxyObj)? AopUtils.getTargetClass(proxyObj) : proxyObj.getClass();
    }

}

添加了个观察者注解@Observer 来标识观察者类。对@MessageListener 的value属性去除默认值,强制性限制value必填。

package com.dgw.hostel.observer;

import java.lang.annotation.*;

/**
 * 观察者,用来标识接收消息的类
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ObServer {

}
package com.dgw.hostel.observer;

import org.springframework.stereotype.Indexed;

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface MessageListener {

    //消息主题
    String value();

    //执行顺序
    int order() default -1;
}

对建造者类稍作修改,改为Observe来获取

package com.dgw.hostel.observer;

import com.dgw.hostel.util.SpringContextUtil;

import java.util.Map;
import java.util.Set;

/**
 * 用建造者模式,创建观察者对象
 */
public class ObServerBuider {


    /**
     * 建造者方法
     */
    public static ProductServer buider(String msgType) {
        //发送者
        ProductServer productServer = new ProductServer(msgType);

        //获取观察者
        Map<String, Object> beans = SpringContextUtil.getBeansWithAnnotation(ObServer.class);
        Set<String> strings = beans.keySet();
        for (String key : strings) {
            Object object=beans.get(key);
            //将观察者添加到发送者集合中
            productServer.addObServer(object);
        }
        return productServer;
    }


}

对生产者类改为可变参数,只要接收端和发送端参数列表一致。就可以发送多个参数。

package com.dgw.hostel.observer;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.support.AopUtils;


import java.lang.reflect.Method;
import java.util.*;

/**
 * 生产者,发送消息
 */
public class ProductServer {

    private String msgType;

    private List<Object> list;

    public ProductServer(String msgType){
        list=new ArrayList<>();
        this.msgType=msgType;
    }

    public void addObServer(Object object) {
        list.add(object);
    }

    //发送消息测试
    public void  sendMessage(Object ... message) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (Object object : list) {
                try {
                    Class<?> clazz = getTargetClass(object);
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType)) {
                            object.getClass().getMethod(method.getName(),method.getParameterTypes()).invoke(object,message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //发送消息,有顺序的执行
    public void  sendOrderMessage(Object ... message) {
        if (CollectionUtils.isNotEmpty(list)) {
            Set<Integer> orders = new TreeSet<>();
            Map<Integer,Object> targetObj=new HashMap<>();
            Map<Integer,Method> targetMethods=new HashMap<>();
            for (Object object : list) {
                try {
                    Class<?> clazz = getTargetClass(object);
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MessageListener messageListener = method.getAnnotation(MessageListener.class);
                        if (messageListener!=null && messageListener.value().equals(this.msgType) && messageListener.order() > -1) {
                            int order = messageListener.order();
                            orders.add(order);
                            targetObj.put(order,object);
                            targetMethods.put(order,method);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (orders.size() > 0) {
                for (Integer order : orders) {
                    try {
                        Object obj = targetObj.get(order);
                        Method method = targetMethods.get(order);
                        obj.getClass().getMethod(method.getName(),method.getParameterTypes()).invoke(obj,message);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }


    /**
     * 根据代理对象获取目标对象的类类型(处理有aop代理对象时,拿不到方法上的注解)
     * @param proxyObj
     * @return
     */
    private Class<?> getTargetClass(Object proxyObj){
        return AopUtils.isAopProxy(proxyObj)? AopUtils.getTargetClass(proxyObj) : proxyObj.getClass();
    }

}