java中的代理设计模式

1、场景:
不需要调用者关注入参是如何变化的,只需要知道在什么情况下使用哪个实现类就可以。所以设计了代理模式,代理本来的接口,实现一个接口根据代理对象的不同,获取不同的时间参数,查询数据。
2、涉及类:
HandlerBeanDefinitionRegistry :Bean注册管理器
CpHistoryProxyFactoryBean:代理bean,入口类
CpHistoryProxyBeanFactory :Bean工厂 , 通过反射new代理对象
CompareHistoryProxyHandler :代理类 ,具体的代理逻辑

3、具体代码
3.1 HandlerBeanDefinitionRegistry

package com.jd.crm.board.proxy;

import com.jd.crm.board.service.HistoryDispatcherService;
import com.jd.crm.board.service.RealDispatcherService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 容器注册代理bean
 *项目启动就初始化 HandlerBeanDefinitionRegistry ,实现代理bean的注册
 *
 */
@Component
public class HandlerBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
	
	 private ApplicationContext applicationContext;
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
			throws BeansException {
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry)
			throws BeansException {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HistoryDispatcherService.class);
        GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
        definition.setBeanClass(CpHistoryProxyFactoryBean.class);
        definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionRegistry.registerBeanDefinition("historyCompareDispatcherService", definition);
        
        BeanDefinitionBuilder yoybuilder = BeanDefinitionBuilder.genericBeanDefinition(HistoryDispatcherService.class);
        GenericBeanDefinition yoyDefinition = (GenericBeanDefinition) yoybuilder.getRawBeanDefinition();
        yoyDefinition.setBeanClass(YoyHistoryProxyFactoryBean.class);
        yoyDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionRegistry.registerBeanDefinition("historyYoyDispatcherService", yoyDefinition);

        BeanDefinitionBuilder wowbuilder = BeanDefinitionBuilder.genericBeanDefinition(HistoryDispatcherService.class);
        GenericBeanDefinition wowDefinition = (GenericBeanDefinition) wowbuilder.getRawBeanDefinition();
        wowDefinition.setBeanClass(WowHistoryProxyFactoryBean.class);
        wowDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionRegistry.registerBeanDefinition("historyWowDispatcherService", wowDefinition);

        BeanDefinitionBuilder dodbuilder = BeanDefinitionBuilder.genericBeanDefinition(RealDispatcherService.class);
        GenericBeanDefinition dodDefinition = (GenericBeanDefinition) dodbuilder.getRawBeanDefinition();
        dodDefinition.setBeanClass(DodHistoryProxyFactoryBean.class);
        dodDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionRegistry.registerBeanDefinition("historyDodDispatcherService", dodDefinition);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
	
}

3.2 CpHistoryProxyFactoryBean

package com.jd.crm.board.proxy;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.jd.crm.board.service.HistoryDispatcherService;

@Slf4j
@Data
public class CpHistoryProxyFactoryBean implements FactoryBean<HistoryDispatcherService>, ApplicationContextAware {
    @Override
    public HistoryDispatcherService getObject() throws Exception {
        Object object = CpHistoryProxyBeanFactory.newMapperProxy();
        return (HistoryDispatcherService) object;
    }
    @Override
    public Class<?> getObjectType() {
        return HistoryDispatcherService.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		CpHistoryProxyBeanFactory.setApplicationContext(applicationContext);		
	}
   
}

3.3 CpHistoryProxyBeanFactory

package com.jd.crm.board.proxy;

import java.lang.reflect.Proxy;

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

import com.jd.crm.board.service.HistoryDispatcherService;

@Component
public class CpHistoryProxyBeanFactory{
	
	private static ApplicationContext applicationContext;
	
    public static <T> T newMapperProxy() {
        CompareHistoryProxyHandler handler = new CompareHistoryProxyHandler(applicationContext);
        return (T) Proxy.newProxyInstance(HistoryDispatcherService.class.getClassLoader(), new Class[]{HistoryDispatcherService.class}, handler);
    }

	public static void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		applicationContext = arg0;
		
	}

}

3.4 CompareHistoryProxyHandler

package com.jd.crm.board.proxy;

import com.jd.crm.board.common.CompareDateType;
import com.jd.crm.board.dao.BaseQuery;
import com.jd.crm.board.service.HistoryDispatcherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 代理逻辑
 * 对比逻辑:日期转化为上一个大促的日期 格式不包含时分秒,dao层获取全天累计数据
 * @author lvshoawei3
 *
 */
@Slf4j
public class CompareHistoryProxyHandler implements InvocationHandler{
	
	private  HistoryDispatcherService subject; 
	private ApplicationContext applicationContext;
	
	CompareHistoryProxyHandler(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		init();
		String date = null;
		if(args[0] instanceof String){
			date = (String)args[0];
		}
		if (args[0] instanceof BaseQuery){
			date = ((BaseQuery) args[0]).getDate();
		}
		String cpDate = CompareDatestrategy.mapDate(date, CompareDateType.getCompareDateByDate(date));
	//	log.info("===========cp date before:{}, date mapped:{}", date, cpDate);
		if(args[0] instanceof String){
			args[0] = cpDate;
		}
		if (args[0] instanceof BaseQuery){
			//这里不要直接改变原来的Query对象里的值
			BaseQuery copyQ = new BaseQuery();
			BeanUtils.copyProperties(args[0], copyQ);
			copyQ.setDate(cpDate);
			args[0] = copyQ;
		}
		return method.invoke(subject, args);
	}
	
	private void init() {
		if(subject == null) {
			HistoryDispatcherService historyDispatcherService = (HistoryDispatcherService)applicationContext.getBean("historyDispatcherServiceImpl");
			//HistoryDispatcherService historyDispatcherService = (HistoryDispatcherService)applicationContext.getBean(HistoryDispatcherService.class);
			this.subject = historyDispatcherService;
		}
	}
}
posted @ 2024-06-18 14:02  新手源  Views(4)  Comments(0Edit  收藏  举报