6

我在 Spring Controller 中使用内部类。从它的父类超类访问受保护的字段/方法时遇到问题。

研究表明,这是由某种方式的不同类加载器引起的,但我对 Spring 的了解还不够确定。

class SuperBaseController {
    protected String aField;

    protected void aMethod() {

    }
}

@Controller
class OuterMyController extends SuperBaseController {

    class Inner {

        public void itsMethod() {
            // java.lang.IllegalAccessError: tried to access method
            aMethod();
        }

        public void getField() {
            // java.lang.IllegalAccessError: tried to access field
            String s = aField;
        }
    }

    void doSomething () {
        // Obviously fine.
        aMethod();
        // Fails in the Inner method call.
        new Inner().itsMethod();

        // Obviously fine.
        String s = aField;
        // Fails in the Inner method call.
        new Inner().getField();
    }
}

是否有任何简单的技术可以避免/解决此问题?最好是那些不涉及制作字段/方法的public

我已经确认ClassLoader外部类的属性与超类的属性不一样。

4

3 回答 3

0

怎么样:

class OuterMyController extends SuperBaseController {
    private String getAField() { return super.aField; }
    protected void aMethod() { super.aMethod(); }
    ...
}

现在内部类使用其外部类的方法,因此没有非法访问,并且外部类的方法可以访问基类的受保护字段。

于 2017-12-19T12:19:29.067 回答
0
class SuperBaseController {
protected String aField;

protected void aMethod() {

    }
}

@Controller
class OuterMyController extends SuperBaseController {


    public void itsMethod() {
        aMethod();
    }

    public void getField() {
        String s = aField;
    }

class Inner {
    public void innerItsMethod() {
        itsMethod();
    }
    public void innerGetField() {
    String s = getField();
    }
}

void doSomething () {
    aMethod();
    new Inner().itsMethod();
    String s = aField;
    new Inner().getField();
    }
}

这行得通吗?

此外,您可能必须定义哪个对象正在运行该方法。(例如 Inner.getField() 或 SuperBaseController.aMethod())

于 2017-12-24T04:28:07.953 回答
0

我创建了以下类:

public class BaseController
{
    protected String field;
    protected void method()
    {
        System.out.println("I'm protected method");
    }
}

@RestController
@RequestMapping("/stack")
public class StackController extends BaseController
{
    class Inner
    {
        public void methodInvocation()
        {
            method();
        }
        public void fieldInvocation()
        {
            field = "Test";
        }
    }
    @RequestMapping(value= {"/invoca"}, method= {RequestMethod.GET})
    public ResponseEntity<String> invocation()
    {
        Inner in = new Inner();
        in.fieldInvocation();
        in.methodInvocation();
        return new ResponseEntity<String>("OK", HttpStatus.OK);
    }
}

我尝试调用其余服务,但没有问题。现在我将这个配置用于 Spring(基于注解的注解):

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.spring.controller" })
@PropertySource( value={"classpath:config.properties"}, encoding="UTF-8", ignoreResourceNotFound=false)
public class DbConfig
{
}


@Configuration
@EnableWebMvc
@Import(DbConfig.class)
@PropertySource(value = { "classpath:config.properties" }, encoding = "UTF-8", ignoreResourceNotFound = false)
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
}

如您所见,我使用了@Import注释,并且在我的 web.xml 中使用了以下配置:

<servlet>
    <servlet-name>SpringDispSvlt</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>it.WebMvcConfig</param-value>
    </init-param>
    <init-param>
        <param-name>dispatchOptionsRequest</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

通过使用此配置,我在调用内部类中的受保护字段和/或方法时没有问题

如果您不能使您的配置适应这个..您可以发布您使用的配置吗?

我希望它有用

安杰洛

于 2017-12-19T11:53:01.133 回答