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的时候其实是忽略了访问权限的限制的!