码迷,mamicode.com
首页 > 编程语言 > 详细

【原】通过Spring结合Cglib处理非接口代理

时间:2019-12-05 11:37:51      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:return   需要   eem   启用   方法调用   ace   set   else   err   

前言:

  把之前做的一个基于Spring扩展Cglib的代理记录一下,防止记忆丢失。

 

Jdk动态代理是基于接口层的代理,但基于的类的代理只能通过字节码层面代理,在一个项目中,很多方法调用是基于类方法的调用,如果要加入代理,是很麻烦的事情,最简单的无非如下:

CglibCacheProxy cacheMethodInterceptor = new CglibCacheProxy();
AgreementHotelPercentService proxyAgreementHotelPercentService = (AgreementHotelPercentService)cacheMethodInterceptor.createProxyObject(agreementHotelPercentService);
AgreementAndMemberHotelPercent agreementAndMemberHotelPercent = proxyAgreementHotelPercentService.getHotelPercent(filterList);  

上面的代码就是通过new一个Cglib工具类,然后需要代理的类丢进去,这么看起来是没什么问题,如果一个项目里有几十个这样的代码需要改造,出现问题以及效率低下可以想象,于是想到代理模式,把公共的代理方法抽取出来,问题是如何才能知道哪个类哪个方法要代理?如何代理?

 

基于Spring实现后置处理

大致思路就是目前所有的bean都是Spring集中管理,所以我们可以在Spring加载完后,再通过某个方式拿出需要代理的Bean,可以通过注解方式,判断是否包含这个注解,如果是就创建代理类。

1. BeanPostProcessor简介

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下

 
public interface BeanPostProcessor {
    //bean初始化方法调用前被调用
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    //bean初始化方法调用后被调用
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
方法说明
postProcessBeforeInitialization 实例化、依赖注入完毕,
在调用显示的初始化之前完成一些定制的初始化任务
postProcessAfterInitialization 实例化、依赖注入、初始化完毕时执行

  

2.自定义 CglibCachePostBeanProcessor 、

public class CglibCachePostBeanProcessor implements BeanPostProcessor{
    @Override
    public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException{
        if(bean.getClass().isAnnotationPresent(CglibCache.class)){
            //判断是代理的类
            CglibCache cglibCache = bean.getClass().getAnnotation(CglibCache.class);
            if(cglibCache.isScan()){
                return CglibCacheProxy.CglibCacheProxy(bean);
            }
        }else{
            return bean;
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanNames) throws BeansException{
        return bean;
    }
}
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CglibCache {
    //是否启用扫描
    boolean isScan() default true;
}
 public static Object CglibCacheProxy(Object bean){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(bean.getClass());//被代理的类
        enhancer.setCallback(new CacheMethodInterceptor(bean));
        return enhancer.create();
    }

 

2.Cglib代理类处理

public class CacheMethodInterceptor implements MethodInterceptor{


    CacheStorageService cacheStorageService;


    //代理对象
    private Object target;

    public CacheMethodInterceptor (Object target){
        this.target = target;
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable{
        Object result = null;
        Cache cacheable = method.getAnnotation(Cache.class);
        if(cacheable!=null){
            //自定义业务逻辑
        }
        return  method.invoke(target,args);
    }

  
}

  

 

【原】通过Spring结合Cglib处理非接口代理

标签:return   需要   eem   启用   方法调用   ace   set   else   err   

原文地址:https://www.cnblogs.com/zdd-java/p/11988174.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!