SpringIOC底层之Java的反射机制

SpringIOC理解

IOC被称之为控制反转,什么是控制反转呢?

例子:在没有Spring之前,我们创建对象的方式为 new 具体对象();

假设 new User(); 而User的构造方法所需参数只有一个UserInfo类;

public class User {
    private UserInfro userInfro;

    public User(UserInfro userInfro) {
        this.userInfro = userInfro;
    }
}

此时创建一个User对象需要先创建一个UserInfo对象

User user=new User(new UserInfro);

而IOC干了干啥呢?

就是它自己创建了这个User对象(在项目启动过程中);

不只各位有没有发现在使用ssm或ssh整合的项目中,我需要一个对象时,用@Autowired或@Resource注解就能直接获得,没有关心该对象与其他对象的关系;

这就是Spring所提供的IOC为我们做的事情;

在启动项目过程中Spring会我们自动去找类与类之间的依赖关系,我们需要的时候直接获取就可以得到,省略了创建对象所需的步骤;

而IOC的底层是DI(依赖注入),而DI依赖于Java的反射机制;

Java的反射机制

什么是Java的反射机制

动态获取类的信息以及动态调用对象的方法称为Java的反射(Reflection)机制。反射提供了封装程序集、模块和类型的对象。在Java运行时环境中,对于任意一个类的对象,可以通过反射获取这个类的信息。(直接copy的)

说白话就是能在运行期间获得类的方法 构造函数 变量等;

在学习反射机制之前,提问一个问题?

假设有一个类中有某个方法 被private修饰,那么该方法能被其他类访问吗?

在没有接触Java的反射机制之前,我的答案可能与大部分人的答案相同,那就是不能。

毕竟在java关键字中三个修饰符

private:只允许本类访问

protected:只允许该包下的类访问

public:公共方法 ,所有类皆可以访问

而在·Java的反射机制中却可以实现对private 方法 或变量的获取(不知道你们哭了没,反正我感觉被骗了)

 

现在开始学习Java的反射机制;

所用到的类User类

public class User {

    public User() {
    }

    public String getAge01(String u){
        System.out.println("getAge01"+u+"年龄为12岁");
        return null;
    }
    private String getAge02(){
        System.out.println("getAge02年龄为12岁");
        return null;
    }

}

 User类中包含一个空的构造函数,一个公共的方法,一个私有的方法;

1.首先通过反射获取到指定的类。

定义一个main函数:

public  static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> user = Class.forName("com.example.User");
        System.out.println(user);
}

打印日志为:class com.example.User

2.创建此实例对象

    public  static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> clazz = Class.forName("com.example.User");
        User user  = (User) clazz.newInstance();
    }

此时User对象已经被创建完成(这只是创建对象的一种方式 其余还有 new 对象(),User.class等,此文档不做详细描述)

3.通过反射机制获取到User实例的方法 构造函数 变量等

按照步骤2的话 我们此时也可以user.getAge01();方式获取方法;

此刻采用反射机制去获取getAge01方法

    public  static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> clazz = Class.forName("com.example.User");
        User user  = (User) clazz.newInstance();
        System.out.println("Class name="+clazz.getName());
        Method getAge01 = clazz.getMethod("getAge01", String.class);
        getAge01.invoke(user,"dd");
    }

控制台打印:

Class name=com.example.User
getAge01dd年龄为12岁

与预期结果一致;

以相同的方式执行getAge02方法(该方法为private方法);

Class name=com.example.User
Exception in thread "main" java.lang.NoSuchMethodException: com.example.User.getAge02()
	at java.lang.Class.getMethod(Class.java:1786)
	at com.example.TestIOC.main(TestIOC.java:13)

出现错误信息 : NoSuchMethodException

这是因为该方法为private修饰不可被访问

只需修改代码为:

Class<?> clazz = Class.forName("com.example.User");
        User user  = (User) clazz.newInstance();
        System.out.println("Class name="+clazz.getName());
        Method getAge02 = clazz.getDeclaredMethod("getAge02");
        getAge02.setAccessible(true);
        getAge02.invoke(user);

 打印日志为:

Class name=com.example.User
getAge02年龄为12岁

 

getDeclaredMethodgetMethod的区别

getMethod指代能获取当前类的公共方法及extends的方法

getDeclaredMethod指代能获取当前类除extends方法之外的方法包括 public private protected等

所以此处使用 getDeclareMethod获取私有方法

而使用setAccessible 设置为true的作用为让此私有方法可供外部调用

不设置的外会出现如下错误:

Class name=com.example.User
Exception in thread "main" java.lang.IllegalAccessException: Class com.example.TestIOC can not access a member of class com.example.User with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Method.invoke(Method.java:491)
	at com.example.TestIOC.main(TestIOC.java:15)

这样我们就通过Java的反射机制调用了类的内部私有方法;

当然你也可以通过反射机制的API获取私有的变量 构造函数等,此处就不多做解释了,万变不离其宗;

贴常用API链接

https://blog.csdn.net/zhou920786312/article/details/81029433

注意:使用反射机制时也会破坏封装类的安全性,在实际项目中酌情使用

前人栽树,后人乘凉,快哉;

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值