当内部类访问受保护的外部类超级

时间:2017-12-08 11:21:36

标签: java spring inner-classes superclass illegalaccessexception

我在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属性与超类的属性不同。

3 个答案:

答案 0 :(得分: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>

通过使用此配置,我在调用内部类

中的受保护字段和/或方法时没有任何问题

如果你无法使你的配置适应这个..你可以发布你使用的配置吗?

我希望它有用

安吉洛

答案 1 :(得分:0)

怎么样:

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

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

答案 2 :(得分: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())