spring容器与java访问权限的关系!

java中的访问控制权限有:

public:无限制 任何人都能访问

protected:只允许在本类中相互调用,还可以由基于父类的子类来调用(即子类可以调用父类中的protected定义的参数或者方法)

默认:默认的权限为同包类调用(即com.xx能调用com包下的其他类,属性和方法,但没法调用com.demo.xx下由默认权限定义的类或者属性或者方法)

private:私有权限,只能在本类中相互调用,不对外开放

 

public class Dem {

    private Dem () {}
    
    public static Dem dem () {
        return new Dem();
    }
}

 

可以将构造方法定义为私有方法,可以控制对象的创建。通过静态方法dem()来创建对象,这样可以防止该类被继承(由于继承的子类会优先调用父类的构造方法).

 

稍微了解了java的权限控制之后来,突然发现一个问题:

spring容器是通过类的构造方法或者set方法等方式将bean注入到容器中的,那么如果将这些方法都设置为private私有的情况下,spring还能正常的创建对象并存到容器中嘛?

答案是可以的。

 

 

自己写了一个简单的测试Demo 将一个类的构造方法定义为private私有的,然后通过@component注解在容器初始化的时候正常被扫描到

发现容器中存在这个bean的对象,说明被正常的创建了。明明是私有的构造方法却能被正常创建。

 

原因在于Spring源码中的反射无视了java的权限控制。

fields[i].setAccessible(true);  

public void setAccessible(boolean flag) throws SecurityException {  
    SecurityManager sm = System.getSecurityManager();  
  //根据是否设置了系统的安全性来获得访问private的权限
if (sm != null) sm.checkPermission(ACCESS_PERMISSION); setAccessible0(this, flag); } //当前定义的唯一名称是suppressAccessChecks,它允许取消由反射对象在其使用点上执行的标准 Java 语言访问检查 - 对于 public、default(包)访问、protected、private 成员。 static final private java.security.Permission ACCESS_PERMISSION = new ReflectPermission("suppressAccessChecks");

 

反射在初始化需要的实例时就设置了System.setSecurityManager 系统安全性。

所以当spring在初始话容器的时候通过反射来创建bean的时候其实是忽略了访问权限的限制的!

 

posted @ 2018-05-16 10:51  粗鲁师太  阅读(190)  评论(0编辑  收藏  举报