反射与代理+spring Bean

文章介绍了Java的反射机制,包括如何通过.class对象获取类信息和动态调用方法。接着讨论了代理的概念,展示了如何通过代理类执行目标类的方法。随后,文章提到了Spring框架中的动态代理及其在bean初始化过程中的作用。最后,简要探讨了Spring事务管理,强调了只有代理对象才能触发事务处理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、java反射机制

java在new出一个对象之后,实际上是将.java文件编译成.class文件,然后jvm加载.class文件并生成.class对象。

而反射则与之相反,通过.class对象反编译获取到.java文件中的属性。

反射的定义:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
 

反射的使用:

    // 获取反射class对象的三种方式
    public static void main(String[] args) throws ClassNotFoundException {
        StringUtils stringUtils = new StringUtils();
        // 1、new出对象之后,调用getClass()方法
        Class<StringUtils> aClass1 = (Class<StringUtils>) stringUtils.getClass();
        
        // 2、类名.class
        Class<StringUtils> aClass2 = StringUtils.class;
        
        // 3、Class.forName()方法
        Class<?> aClass3 = Class.forName("com.example.dashboard.util.StringUtils");

        System.out.println(aClass1.getName());
        System.out.println(aClass1==aClass2);
        System.out.println(aClass1==aClass3);

        /**
         * 打印结果:
         * com.example.dashboard.util.StringUtils
         * true
         * true
         */
      }

2、代理

代理:简单的说就是用代理类去执行普通类的方法,简单示例如下:通过Proxy类执行A类中的print方法。

public class Test {
    public static void main(String[] args) {
        A a = new A();
        Proxy proxy = new Proxy(a);
        proxy.print();
    }
}

class A {
    public void print() {
        System.out.println("A类");
    }
}

class Proxy {

    private A a;

    public Proxy() {
    }

    public Proxy(A a) {
        this.a = a;
    }

    public void print() {
        a.print();
    }

}

3、spring 动态代理

在JVM运行的过程中创建对象。

4、spring启动流程

package com.example.demo.beanDefinition;

import org.springframework.stereotype.Component;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

public class DingApplicationContext {

    private Class configClass;

    private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();

    public DingApplicationContext(Class configClass) {
        this.configClass = configClass;

        if(configClass.isAnnotationPresent(MyComponentScan.class)){

            MyComponentScan annotation = (MyComponentScan) configClass.getAnnotation(MyComponentScan.class);
            String path = annotation.value(); // 获取到包名

            path = path.replace(".", "/");

            ClassLoader classLoader = DingApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);  // 拼接出来绝对路径
            File file = new File(resource.getFile());

            System.out.println(file);

            if (file.isDirectory()) {
                File[] files = file.listFiles();

                for (File f : files) { // 文件夹,过滤出来需要加载的bean
                    String fileName = f.getAbsolutePath();
                    System.out.println(fileName);

                    if (fileName.endsWith(".class")) { // 需要加载的必然是.class文件

                        String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
                        className = className.replace("\\",".");
                        try {
                            Class<?> clazz = classLoader.loadClass(className);
                            if(clazz.isAnnotationPresent(Component.class)){
                                String beanName = clazz.getAnnotation(Component.class).value();

                                //这个使用以下spring的默认名字取用方法
                                if("".equals(beanName)){
                                    beanName = Introspector.decapitalize(clazz.getSimpleName());
                                }


                                // 需要加载的bean
                                BeanDefinition beanDefinition = new BeanDefinition();
                                beanDefinition.setType(clazz);
                                beanDefinition.setScope("singleton");  // 需要通过注解@scope进行判断

                                beanDefinitionMap.put(beanName, beanDefinition);

                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }


                    }

                }
            }
        }
        
        // 获取单例bean
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (beanDefinition.getScope().endsWith("singleton")) {
                Object bean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, bean);
            }
        }
        
    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class clazz = beanDefinition.getType();

        try {
            Object instance = clazz.getConstructor().newInstance();

            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


        return null;
    }


    public Object getBean(String beanName) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition == null) {
            throw new NullPointerException();
        } else {
            String scope = beanDefinition.getScope();
            if (scope.equals("singleton")) {
                Object bean = singletonObjects.get(beanName);
                if (bean == null) {
                    Object o = createBean(beanName, beanDefinition);
                    singletonObjects.put(beanName, o);
                    return o;
                }
                return bean;
            } else {
                return createBean(beanName, beanDefinition);
            }
        }
    }
}
@MyComponentScan(value = "com.example.demo.beanDefinition")
public class AppConfig {
}

@Data
public class BeanDefinition {

    private Class type;

    private String scope;
}

@Component("mainService")
public class MainService {

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponentScan {

    String value() default "";
}


public class Test {

    public static void main(String[] args) {
        DingApplicationContext applicationContext = new DingApplicationContext(AppConfig.class);

        MainService mainService = (MainService) applicationContext.getBean("mainService");

    }
}

5、bean的初始化

bean初始化的步骤:

1、生成beanDefinition对象

2、将需要生成的bean信息注入beanDefinition

3、User.class -> 推测构造方法-> 普通对象 -> 依赖注入 -> 初始化前@PostConstruct -> 初始化 实现InitializingBean接口实现afterPropertiesSet() -> 初始化后 AOP -> 代理对象 -> 单例放入单例池Map -> Bean对象

构造:如果多个,存在无参,使用无参;没有无参,可以用@Autowired指定;若都没有报错 

代理对象 继承 User, 内部存在属性tagert指向普通对象

AOP之后会产生代理对象

spring事务分析:

// spring事务的代码分析, 只有代理对象能触发
class UserProxy extends User {
    User target;

    public void test() {
        // 1、判断是否需要处理事务 @Transactional
        // 2、建立一个新的数据库链接conn  ThreadLocal<Map<DataSource,conn>>
        //   事务管理器中的数据链接conn1  // 如果conn1!=conn2 事务也会失效
        // 3、conn.autocommit = false
        target.test(); // 执行数据库操作, sql1 sql2  // jdbc中的数据链接conn2
        // 方法无异常 conn.commit(); // 异常 conn.rollback() 
    }
}

参考:1、手写模拟Spring_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值