spring原理粗略 +手写简单的spring

本文详细阐述了Spring框架中Bean的创建过程,包括无参构造、依赖注入、初始化方法的使用,以及AOP如何通过代理对象和切面实现。同时讨论了事务管理中遇到的问题和解决方案,以自定义的ChenLeiApplicationContext为例,展示了Spring底层的实现原理。
摘要由CSDN通过智能技术生成

spring底层原理解析

Bean创建的生命周期

UserService-->无参构造(推断构造方法)-->普通对象-->依赖注入-->初始化前(@PostConstruct)-->初始化(InitializingBean)-->初始化后(AOP)-->代理对象-->完整的Bean

判断是否要进行生成代理对象

1.找出所有的切面Bean

2.遍历所有的切面方法

3.缓存到map,在哪个类型的对象上进行切入,切入的方法

4.判断当前创建的对象,是否有切面的缓存,如果有则执行的时候,从缓存中拿到切面的方法,来执行

UserServiceProxy-->代理对象-->代理对象.target=被代理的普通对象(之前被注入的普通对象)

无参构造(推断构造方法)

spring默认通过无参构造来初步构建对象,当然,当只有一个有参构造的时候,会用这一个有参,但是当多个有参构造的时候就需要声明用哪一个了,也就是spring会根据当前类的所有的构造方法,来判断用哪一个,判断不了的时候就需要认为设置;

@Component
public class UserService implements InitializingBean {
​
    private OrderService orderService;
    private String s;
​
    public void doSomething(){
        System.out.println("do");
    }
​
    @PostConstruct
    public void a(){
        //从数据库中给orderService赋值
    }
​
    public void afterPropertiesSet() throws Exception {
        //从数据库中给orderService赋值
    }
​
/*    public UserService() {
    }*/
​
    public UserService(OrderService orderService) {
        this.orderService = orderService;
    }
    @Autowired //此时就需要声明构造方法
    public UserService(OrderService orderService, String s) {
        this.orderService = orderService;
        this.s = s;
    }
}

依赖注入

依赖注入的引入:

@Component
public class UserService {
    @Autowired
    private OrderService orderService;
​
    public void doSomething(){
        System.out.println("do");
    }
}

引用

public class SpringStater {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        //容器获得对象
        UserService userService = context.getBean(UserService.class);
        //自己new的对象
        UserService userService1 = new UserService();
        //区别在于,通过容器拿到的对象userService中orderService有值,而自己创建出来的userService1中orderService为空,而在UserService.calss中,只有一个默认的空参构造,所以肯定spring最开始也是调用空参构造,后续的操作让对象中有了orderService(依赖注入)
        //比如 通过声明的注解来进行设置
          for (Field field : userService1.getClass().getFields()) {
            if(field.isAnnotationPresent(Autowired.class)){
                field.set(userService1,"orderService");
            }
        }
    }
}

初始化前(@PostConstruct)-->初始化(InitializingBean)

比如上面的的orderservice是需要从数据库查询得到,也就是说我们需要在正式成为Bean之前,就调用a方法,那么我们就要告知spring来做处理

方式1 @PostConstruct;

方式2 InitializingBean--afterPropertiesSet

方式3 AOP来生成代理对象

@Component
public class UserService implements InitializingBean {
    @Autowired
    private OrderService orderService;
​
    public void doSomething(){
        System.out.println("do");
    }
​
    @PostConstruct
    public void a(){
        //从数据库中给orderService赋值
    }
​
    public void afterPropertiesSet() throws Exception {
        //从数据库中给orderService赋值
    }
}
​

注入的时候,先根据类型去查找,然后根据名字匹配;当找到的对象不唯一或者找不到的时候就会报错

初始化后(AOP)

spring的动态代理使用的CGlib,用的是继承

切面

@Component
@Aspect
public class UserAspect {
​
    @Before("execution( public void com.chenlei.pojo.UserService.doSomething())")
    public void userBefore(JoinPoint joinPoint){
        System.out.println("before");
    }
}
​

配置类开启切面

@ComponentScan("com.chenlei")
@EnableAspectJAutoProxy
public class MyConfig {
​
}

真正执行时,有值

代理类似以下

public class UserServiceProxy extends UserService {
    //其实这里创建的代理对象,虽然都有这些属性,但是spring的bean的生命周期中,它的AOP之后,并没有对代理对象进行依赖注入,代理对象的属性值为空,所以它其实是在创建代理对象的时候,把之前创建的普通对象给到代理对象,调用doSomething方法时,用的是之前的普通对象target,target是在之前进行了注入的,所以它的OrderService有值
    private UserService target;
    @Override
    public void doSomething() {
        //执行@before
        
        //最终是普通对象执行doSomething
        target.doSomething();
    }
}

spring事务

spring事务失效的问题,

 */
@Component
public class UserService implements InitializingBean {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Transactional
    public void test(){
        jdbcTemplate.execute("insert t1 values (1,1,1,1)");
        b();
    }
    
    @Transactional(propagation = Propagation.NEVER)//只能在不存在事务的时候执行
    public void b(){
        jdbcTemplate.execute("insert t1 values (2,2,2,2)");
    }
  }

此时,我们插入1数据的时候,按理来说,我们是不能进行数据2的插入,因为数据2添加了Propagation.NEVER;

但实际情况是我们执行成功了

public class UserServiceProxy extends UserService {
​
    private UserService target;
    @Override
    public void doSomething() {
        //获取链接
        //关闭自动提交
        //普通对象执行test
        target. test();-->b()是target普通对象在执行,没有代理对象 因此不存在spring事务
    }
}

原因是因为在数据1test()这里开启了事务,但是这个事务是开启在代理对象上的,而代理对象在执行test方法时,先去执行了,获取链接,关闭自动提交,当执行到test()时,是原来的普通对象在执行,也就是说 b();也是普通对象在执行,所以事务就失效了(而spring事务生效的关键就是代理对象来控制了非自动提交),所以解决办法是,在当前对象中,注入自己(这里的自己其实就是代理对象),同样用代理对象来执行,事务就会生效

@Component
public class UserService implements InitializingBean {
​
    @Autowired //注入代理对象
    private UserService userService;
​
    @Autowired
    private JdbcTemplate jdbcTemplate;
​
    @Transactional
    public void test(){
        jdbcTemplate.execute("insert t1 values (1,1,1,1)");
        userService.b();
    }
​
    @Transactional(propagation = Propagation.NEVER)//只能在不存在事务的时候执行
    public void b(){
        jdbcTemplate.execute("insert t1 values (2,2,2,2)");
    }
}
​

手写一个简单的spring

1.创建我们的applicationContext

public class ChenLeiApplicationContext {
    //配置类
    private Class clazz;
    private Map<String,ChenLeiBeanDefinition> beanDefinitionMap = new HashMap<String, ChenLeiBeanDefinition>();
    //单例池
    private Map<String,Object> singletonBeanMap = new HashMap<String, Object>();
​
    private List<ChenLeiBeanPostProcessor> processorList=new ArrayList<ChenLeiBeanPostProcessor>();
​
​
    public ChenLeiApplicationContext(Class configClazz) {
        //配置类 定义了bean扫描路径
        this.clazz = configClazz;
        //根据扫描路径进行扫描
        scan(configClazz);
        //开始创建单例对象 找到beanDefinitionMap中为单例的
        for (Map.Entry<String, ChenLeiBeanDefinition> entry : beanDefinitionMap.entrySet()) {
            //只要不是原型 是单例就创建
            if (!"prototype".equals(entry.getValue().getScope())) {
                Object bean = createBean(entry.getKey(), entry.getValue());
                singletonBeanMap.put(entry.getKey(),bean);
            }
        }
    }
​
​
    private void scan(Class configClazz) {
        //扫描类路径 获取当前clazz扫描路径
        if (configClazz.isAnnotationPresent(ChenLeiComponentscan.class)) {
            ChenLeiComponentscan componentscanAnnotation = (ChenLeiComponentscan)configClazz.getAnnotation(ChenLeiComponentscan.class);
           //定义的扫描的路径
            String path = componentscanAnnotation.value().replace(".","/");
            ClassLoader classLoader = ChenLeiApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());
            //如果是一个文件夹
            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    String absolutePath = f.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");
                    Class<?> aClass = null;
                    try {
                        aClass = classLoader.loadClass(absolutePath);
​
​
                    if (aClass.isAnnotationPresent(ChenLeiComponent.class)) {
​
                        //在扫描的时候就把processor 创建 并缓存起来 方便 创建bean用
                        //判断aClass类是否是ChenLeiBeanPostProcessor
                        if (ChenLeiBeanPostProcessor.class.isAssignableFrom(aClass)) {
                            ChenLeiBeanPostProcessor instance = (ChenLeiBeanPostProcessor)aClass.getConstructor().newInstance();
                            processorList.add(instance);
                            continue;
                        }
​
                        ChenLeiBeanDefinition beanDefinition = new ChenLeiBeanDefinition();
                        //我们定义的beanName
                        String beanName = aClass.getAnnotation(ChenLeiComponent.class).value();
                        //JDK提供的获取类的首字母小写
                        if("".equals(beanName)){
                            beanName = Introspector.decapitalize(aClass.getSimpleName());
                        }
​
                        beanDefinition.setaClass(aClass);
                        if (aClass.isAnnotationPresent(ChenLeiScope.class)) {
                            //设置我们配置的值
                            String value = aClass.getAnnotation(ChenLeiScope.class).value();
                            beanDefinition.setScope(value);
                        }else {
                            //不配置默认单例
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
​
    public Object getBean(String beanName){
        //如果beanDefinitionMap没有这个key 则说明当前容器中没有定义一个这样的bean
        if (!beanDefinitionMap.containsKey(beanName)) {
            return new NullPointerException();
        }else {
            ChenLeiBeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
​
​
            if("singleton".equals(beanDefinition.getScope())){
                Object  singletonBean= singletonBeanMap.get(beanName);
​
                //beanDefinition的创建是在创建bean之前做的,所以只要是定义了的bean beanDefinition中都会有
                //但是容器中的bean是一个一个创建的,所以当A需要B的时候,B可能还没有被创建
                if (singletonBean==null) {
                    singletonBean  = createBean(beanName, beanDefinition);
                    singletonBeanMap.put(beanName,singletonBean);
                }
​
                //单例从容器中拿
                return singletonBean;
            }else {
​
                //原型(多例)直接根据beanName和beanDefinition创建
                return createBean(beanName,beanDefinition);
            }
​
        }
    }
​
​
    public Object createBean(String beanName,ChenLeiBeanDefinition beanDefinition){
        Class aClass = beanDefinition.getaClass();
​
        Object bean=null;
        try {
            //这里spring 会去推断使用哪一个构造方法 我们简单使用无参构造
            bean = aClass.getConstructor().newInstance();
​
            //根据属性的名来进行注入
            for (Field field : aClass.getFields()) {
                if (field.isAnnotationPresent(ChenLeiAutowired.class)) {
                    field.setAccessible(true);
                    field.set(bean,getBean(field.getName()));
                }
            }
            //初始化前
            for (ChenLeiBeanPostProcessor processor : processorList) {
                //aop 一般在这里使用 cglib来创建代理对象 所以原来的bean就是代理对象
                bean = processor.postProcessBeforeInitialization(bean, beanName);
            }
​
            //initializing
            if (bean instanceof ChenLeiInitializingBean) {
                ((ChenLeiInitializingBean) bean).afterPropertiesSet();
            }
​
            //postprocess 这种就是所有的bean都会经过所有的processor处理
            //想要特别的bean处理 只需要在postProcessBeforeInitialization 实现逻辑就行
            for (ChenLeiBeanPostProcessor processor : processorList) {
                //aop 一般在这里使用 cglib来创建代理对象 所以原来的bean就是代理对象
                bean = processor.postProcessAfterInitialization(bean, beanName);
            }
​
​
​
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return bean;
    }
​
}

定义一个beandefinition,用来保存bean的信息,是否是单例模式,是否懒加载等

public class ChenLeiBeanDefinition {
​
    private Class aClass;//bean的类型
    private String scope;//是否是单例bean
    private boolean lazy;//是否懒加载
​
    public Class getaClass() {
        return aClass;
    }
​
    public void setaClass(Class aClass) {
        this.aClass = aClass;
    }
​
    public String getScope() {
        return scope;
    }
​
    public void setScope(String scope) {
        this.scope = scope;
    }
​
    public boolean isLazy() {
        return lazy;
    }
​
    public void setLazy(boolean lazy) {
        this.lazy = lazy;
    }
}
​

定义一个@conponent 标记哪些是我们要加载bean

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiComponent {
    String value() default "";
}

定义scope 来确定bean是单例还是多例

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiScope {
    //两种类型 singleton单例和 prototype 原型(多例)
    String value()  default"";
}

componentscan

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiComponentscan {
    String value() default "";
}

自动注入

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiAutowired {
}

初始化接口

public interface ChenLeiInitializingBean {
    void afterPropertiesSet();
}

processor

public interface ChenLeiBeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) ;
    Object postProcessAfterInitialization(Object bean, String beanName) ;
}

git地址

陈铁柱/spring

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值