当前位置: 首页 > 面试题库 >

Spring AOP CGLIB代理的字段为null

咸琪
2023-03-14
问题内容

使用vlcj组件,由于AOP代理对象为null,因此自定义组件出现。

MediaList类别

public class MediaList {
    private libvlc_media_list_t mediaListInstance;
    public MediaList(LibVlc libvlc, libvlc_instance_t instance, libvlc_media_list_t mediaListInstance) {
        this.libvlc = libvlc;
        this.instance = instance;
        createInstance(mediaListInstance);
    }
    private void createInstance(libvlc_media_list_t mediaListInstance) {
        logger.debug("createInstance()");
        if(mediaListInstance == null) {
            mediaListInstance = libvlc.libvlc_media_list_new(instance);
        }
        else {
            libvlc.libvlc_media_list_retain(mediaListInstance);
        }

        this.mediaListInstance = mediaListInstance; // <- assignment
        logger.debug("mediaListInstance={}", mediaListInstance);

        mediaListEventManager = libvlc.libvlc_media_list_event_manager(mediaListInstance);
        logger.debug("mediaListEventManager={}", mediaListEventManager);

        registerEventListener();
    }
    public final libvlc_media_list_t mediaListInstance() {
        return mediaListInstance; // <- proxy object return null, if use aop
    }
}

自定义MediaList类

public class TestMediaList extends MediaList {

    public TestMediaList(LibVlc libvlc, libvlc_instance_t instance) {
        super(libvlc, instance);
    }

    public void xTest(String test){
        System.out.println(test);
    }
}

弹簧配置类

@Configuration
public class PlayerBeanConfig {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Resource
    public TestMediaList testMediaList(LibVlc libvlc, libvlc_instance_t instance) {
        return new TestMediaList(libvlc, instance);
    }
}

AOP配置类

@Aspect
public class MediaListAspect {
    @Pointcut("execution(* TestMediaList.xTest(..))")
    private void anyMethod() {
    }

    @Around("anyMethod()")
    public Object lockAndUnlock(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object = joinPoint.proceed();
        return object;
    }
}

测试代码

public static void main(String[] args) {
    boolean b = new NativeDiscovery().discover();

    if (b) {
        springContext = new AnnotationConfigApplicationContext(PlayerBeanConfig.class);

        String[] kkk = new String[]{};
        TestMediaList list = springContext.
                getBean(TestMediaList.class, LibVlc.INSTANCE, LibVlc.INSTANCE.libvlc_new(kkk.length, kkk));

        System.out.println(list.mediaListInstance()); // <- proxy object return null
    } else {
        logger.error("Cannot find vlc lib, exit application");
    }
}

我尝试单步跟踪,当TestMediaList构建完成时。该方法的MediaListInstance()返回正常值,但是当spring返回到代理对象时,将返回null。同时,如果您不使用AOP,我也会尝试正确返回该值。因此,我确定了AOP动态代理中的基本问题,但是我不知道为什么,以前没有遇到过这种情况。

最小的例子

包中的所有类: vod.demo

TargetClass

public class TargetClass {
    private String returnValue;

    public TargetClass() {
        this.returnValue = "Hello World";
    }

    public final String test() {
        System.out.println("TargetClass.test();");
        return returnValue;
    }
}

方面类

@Aspect
public class AspectClass {
    @Pointcut("execution(* vod.demo.TargetClass.*(..))")
    private void targetMethod() {
    }

    @Around("targetMethod()")
    public Object aroundTarget(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("AspectClass.aroundTarget();");
        return joinPoint.proceed();
    }
}

Spring Config类

@Configuration
@EnableAspectJAutoProxy
@Import(AspectClass.class)
public class SpringConfig {
    @Bean
    public TargetClass target() {
        return new TargetClass();
    }
}

客户类别

public class Client {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        TargetClass target = context.getBean(TargetClass.class);
        System.out.println("Client invoke:" + target.test()); // <- output null
    }
}

问题答案:

这是潜在的意外行为的组合。首先,Spring使用CGLIB代理AOP的bean。CGLIB代理是类的动态子类型的实例,该类将所有方法调用委派给类的真实实例。但是,即使代理是子类型的,其字段也不会初始化(即,TargetClass不会调用您的超级构造函数)。在这里可以找到更长的解释。

此外,您的方法

public final libvlc_media_list_t mediaListInstance() {
    return mediaListInstance; // <- proxy object return null, if use aop
}

要么

public final String test() {
    System.out.println("TargetClass.test();");
    return returnValue;
}

final。因此,CGLIB无法覆盖它们以委派给实际实例。这将在Spring日志中得到提示。例如,您会看到

22:35:31.773 [main] INFO  o.s.aop.framework.CglibAopProxy - Unable to proxy method [public final java.lang.String com.example.root.TargetClass.test()] because it is final: All calls to this method via a proxy will NOT be routed to the target instance.

将以上所有内容放在一起,您将获得一个代理实例,该实例在字段中null,并且该代理不能将其委托给实际实例的方法。因此您的代码实际上将调用

public final String test() {
    System.out.println("TargetClass.test();");
    return returnValue;
}

对于returnValue字段为的实例null

如果可以,请更改方法,删除final修饰符。如果不能,则必须重新考虑您的设计。



 类似资料:
  • 我有混合堆栈:EJB和Spring。为了将Spring自动连接到EJB,我使用(不确定这是否会影响我遇到的问题)。 Whlie试图通过以下方式自动连接bean: 我得到错误: 据我所知,问题是使用了JDK代理(因为实现了接口),而我需要cglib代理。 不确定是否相关,但我运行的是glassfish 3.1.x。 和stacktrace(部分,因为我不能在这里公开所有类名:

  • 索引模式中的字段会以列表的方式显示,点击列标题可以按列对表格排序,点击最右边列的 控制 按钮可以编辑指定字段的属性。您可以从 格式 下拉菜单中手动设置字段的格式。具体格式选项依赖于字段类型。 您也可以在 流行度 文本框中设置您需要的该字段的流行度值。点击 更新字段 按钮确认更改,或者点击 取消 返回字段列表。 Kibana 有以下字段类型的格式化: 字符串字段格式化 字符串字段支持 String

  • 我创建了一个名为“cislo_ponuky”的acf字段。它是数字的。 我现在需要的是将其显示为一个名为Nehnutelnosti的自定义post类型中的admin列,其中包含一段“nehnutelinosti”。 函数custom_mycpt_column( $column,$post_id ) { switch ( $column ) { }} 不幸的是,这段代码对我不起作用。

  • 本文向大家介绍java 获取对象中为null的字段实例代码,包括了java 获取对象中为null的字段实例代码的使用技巧和注意事项,需要的朋友参考一下 下面一段简单的代码给大家分享java 获取对象中为null的字段,具体代码如下所述: PS:将Java对象中属性值为null获取到 话不多说,直接贴代码,这里可以进行对json对象参数进行校验的,找到不为空的参数,或者对象所有属性都不为空这样的校验

  • 问题内容: 您能告诉我如何使RequestFactory填充实体代理的实体代理字段吗? 这是父母代理 如您所见,它包含另一个代理作为字段。这是PersonProxy的样子 在我的界面中,我有method 。从数据存储区获取真实组织的DAO类设置其字段,但在客户端中始终为。实际上,RequestFactory甚至从不调用Organization.getContactPerson()。 我的客户电话看

  • 一、功能说明 对黄页分类进行扩展,使之具有自定义模型一般的灵活性 注:本功能默认并不存在,需先安装黄页模块 二、子功能导航 1.添加字段 2.使用字段 三、功能详解 1.添加字段 附加字段的添加和基本模型的自定义字段一致 2.使用字段 导航栏 选择模块 -> 菜单栏 选择 企业黄页下面的 分类管理 -> 子导航 添加产品分类 点击后在弹出的新窗口中选择附属字段管理显示如下图 勾选上您添加的附加字段