Spring源码IOC部分

spring ---> IOC -->DI

 

Dog dog= new Dog();

application.xml--->

IOC 管理

<bean id="dog" class="com.cang.Dog">

Spring 是一个开源轻量级框架,为了解决企业应用复杂的业务

可以说Spring是企业应用开发“一站式” 解决方案

注解:

IOC AOP

Spring 的目标

1,让现有的技术更加容易使用,

2,促进来良好的编程习惯

它坚持的一个原则就是不重复新造轮子;

Spring体系结构

1,Soring Core spring核心,他是框架最基础的部分,提供IOC和依赖注入特性;

2,Spring Context ,Spring 上下文容器,他是BeanFactory功能加强的一个子接口

3,SpringWeb 他提供web应用开发支持

4,Spring MVC 他正对Web应用中MVC思想的实现;

5,Spring DAO 提供JDBC抽象层,简化JDBC编码,同时 ,编码更具有健壮性。

6,Spring ORM 他支持用于流行的ORM框架整合,比如 SPring +Hibemate ,Spring +iBatis,Spring+JDO等框架整合等等。

7,Spring AOP :AOP,面向机切面编程,他提供了与AOP联盟兼容的编程实现

class Test{} bean -->

AOP

@Watch("") //看电影,观察 你有没有买电影票 做一个钱箱控制 ,在进入方法之前可以做一个判断

@Transaction(“”) // 添加一个事务

public void watchMovie (){

}

把这个 bean 初始化之后 放在IOC 容器里面

@Configuration

1,@Configuration 这种更简单

class Test{}

2,与bean.xml 的的联系

效果 一样的

@COmponentScan 扫描规则

1,指定扫描范围;

2,扫描过滤器

3,自定义过滤器

package com.enjoy.cap2.config;
​
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
​
import java.io.IOException;
​
/**
 * MetadataReader读取到当前正在扫描类的信息
 * MetadataReaderFactory  可以获取到类的所有信息
  */
​
​
public class jamesTyperFilter  implements TypeFilter {
​
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
​
       //获取当前类的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //  获取当前正在扫描的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类资源(类路径)
        Resource resource = metadataReader.getResource();
​
        String className = classMetadata.getClassName();
        System.out.println("----->>"+className);
​
        if(className.contains("er")){
            return true; //当我们的类包含er的时候 则匹配成功
        }
​
​
​
        return false;
    }
}
​
​

Spring 是单实例的

单实例和多实例有什么区别?

多实例 :就是你使用的时候才会创建这个bean ,一个实例死掉了 我还可以用另一个实例啊;

单实例: 创建IOC 容器的时候这个bean 就被创建了

@Lazy 懒加载

/**
 *  懒加载 针对的是单实例bean :  默认在容器中启动的时候创建对象
 *  懒加载:容器启动的时候不创建对象,仅当第一次使用 bean的时候才创建 初始化
 * @return
 */

第二课

IOC 就是对我们bean 进行管理: bean 注册实例化 管理

运行测试用例的时候,操作系统是Windows,我就让Lison 这个实例对象到容器

linux : james 这个实例对象到容器中

FactoryBean BeanFactory 的区别?

FactoryBean : 可以把我们的Java实例Bean 通过FactoryBean注入到容器中;

BeanFactory : 从我们的容器中获取实例化后的bean

@Condition 条件注册bean

package com.enjoy.cap5.config;
​
​
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
​
public class WinCondition implements Condition {
​
    /**
     * ConditionContext: 判断条件可以判断条件(环境)
     *
     * @param context
     * @param annotatedTypeMetadata
     * @return
     */
​
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
​
        //能够获取到IOC 容器正在使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
         // 获取当前的环境变量(操作系统是win 还是linux)
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }
​
        return false;
    }
}
​
​
​
package com.enjoy.cap5.config;
​
import com.enjoy.cap1.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class Cap5MainConfig {
    @Bean("person")
    public Person person() {
​
        System.out.println("给容器添加person。。。。。");
        return new Person("person",20);
    }
    @Conditional(WinCondition.class)
    @Bean("lison")
    public Person lison() {
        System.out.println("给容器添加lison。。。。。");
        return new Person("lison",58);
    }
    @Conditional(LinuxCondition.class)
    @Bean("james")//bean 在容器的id 为james ,IOC容器MAP
    public Person james() {
        System.out.println("给容器添加james。。。。。");
        return new Person("lison",20);
    }
}
​

@Import 注册bean

package com.enjoy.cap6.config;
​
import com.enjoy.cap1.Person;
import com.enjoy.cap5.config.LinuxCondition;
import com.enjoy.cap5.config.WinCondition;
import com.enjoy.cap6.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
​
@Configuration
@Import(value ={Dog.class})
public class Cap6MainConfig {
​
    /**
     * 给容器中注册组件
     * 1,@Bean  导入第三方的类包的组件,比如Person为第三方的类,需要在我们的IOC容器中使用
     *,2, 包扫描+组件的标注注解 @ConponentSan :@Controller,@Service,@Reponsitory @Componet) 一般是针对我们自己写的类
     * 3,@Import : 能够快速给容器导入一个组件 注意:@Bean 有点简单
     *
     */
    // 容器启动时初始化person的bean实例
    @Bean("person")
    public Person person() {
        System.out.println("给容器添加person。。。。。");
        return new Person("james",20);
    }
​
}
​
​
​
package com.enjoy.cap6.config;
​
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
​
public class JamesImportSelect implements ImportSelector {
​
   public String[] selectImports(AnnotationMetadata annotationMetadata) {
​
 // 返回全类名
        return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"};
    }
}
​

package com.enjoy.cap6.config;
​
import com.enjoy.cap1.Person;
import com.enjoy.cap5.config.LinuxCondition;
import com.enjoy.cap5.config.WinCondition;
import com.enjoy.cap6.bean.Cat;
import com.enjoy.cap6.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
​
@Configuration
@Import(value ={Dog.class, Cat.class,JamesImportSelect.class,JamesImportBeanDefinitionRegistrar.class})
public class Cap6MainConfig {
​
    /**
     * 给容器中注册组件
     * 1,@Bean  导入第三方的类包的组件,比如Person为第三方的类,需要在我们的IOC容器中使用
     *,2, 包扫描+组件的标注注解 @ConponentSan :@Controller,@Service,@Reponsitory @Componet) 一般是针对我们自己写的类
     * 3,@Import : 能够快速给容器导入一个组件 注意:@Bean 有点简单
     *     a, @Import ( 要导入到容器中的组件): 容器中会自动注册到这个组件,bean 的id 为全类名
     *     b,ImportSelector: 是一个接口 返回需要导入到容器的组件的全类名数组
     *      c,ImportBeanDefinitionRegistrar: 可以手动添加到IOC 容器,所有Bean的注册可以使用BeanDifinitionRegistar,
     *      
     */
    // 容器启动时初始化person的bean实例
    @Bean("person")
    public Person person() {
        System.out.println("给容器添加person。。。。。");
        return new Person("james",20);
    }
​
}

CompoentScan ....

Bean 的生命周期 bean 创建 ----》 初始化 -----》 销毁的过程

我们可以自定义bean初始化和销毁的方法

容器在bean进行到当前生命周期的时候,来调用自定义的初始化和销毁的方法

容器创建过程中: 单实例完全被创建的

package com.enjoy.cap7.config;
​
import com.enjoy.cap1.Person;
import com.enjoy.cap7.bean.Bike;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class Cap7MainConfigLifeCycle {
    @Bean("person")
    public Person person() {
​
        System.out.println("给容器添加person。。。。。");
        return new Person("person",20);
    }
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        return  new Bike();
    }
}
​

多实例

package com.enjoy.cap7.config;
​
import com.enjoy.cap1.Person;
import com.enjoy.cap7.bean.Bike;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
​
@Configuration
public class Cap7MainConfigLifeCycle {
    @Bean("person")
    public Person person() {
​
        System.out.println("给容器添加person。。。。。");
        return new Person("person",20);
    }
    @Scope("protoype")//  多实例
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        return  new Bike();
    }
}

多实例应用场景: 数据库连接池的时候可以用多实例。

生命周期-初始化与销毁2

1, 实现InitalizingBean接口的afterPropertiesSet() 方法,当beanFactory创建号对象,且把bean所有属性设置好之后,会调用这个方法,相当于初始化方法;

2,实现DisposableBean的destory()方法,当销毁时,会把单实例bean进行销毁;

package com.enjoy.cap7.bean;
​
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
​
@Component
public class Train implements InitializingBean, DisposableBean {
​
    // 当我们的bean 销毁时,调用方法
    public Train(){
        System.out.println("Train.........constructor.......");
​
    }
    // 当我们的bean属性复制和初始化完成是调用
    public void destroy() throws Exception {
​
        System.out.println("Train.........destroy.......");
    }
​
    public void afterPropertiesSet() throws Exception {
        System.out.println("Train.........afterPropertiesSet.......");
​
    }
}

生命周期-初始化与销毁3

可以使用JSR250 规范定义的(java规范)两个注解来实现

@PostConstruct: 在Bean 创建完成,且属于赋值 完成后进行初始化,属于JDK 规范注解

@PreDestroy : 在Bean 将被移除之前进行通知,在容器销毁之前进行清理工作

提示: JSR 是由JDK 提供的一组规范

package com.enjoy.cap7.bean;
​
import org.springframework.stereotype.Component;
​
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
​
@Component
public class Jeep {
    public Jeep(){
        System.out.println("Jeep......constructor");
    }
    @PostConstruct
    public  void init(){
        System.out.println("Jeep..... @PostConstruct.......");
    }
    @PreDestroy
  public void destory(){
        System.out.println("Jeep.....  @PreDestroy......");
    }
​
  }

Spring

1, 创建并初始化容器相关的所有processor

2,bean

ping 做的优秀的地方 就是对方法进行拦截, 只用一个注解 processor

public void doOrder(){

A a =new A()

commit();

}

T= cglib.proxyProcess().invoke(bike.class).bike()

通过动态动态代理可以拿到.class 然后直接去调用 类里面的方法

package com.enjoy.cap7.bean;
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
​
@Component
public class JamesBeanPostProcessor  implements BeanPostProcessor {
​
    // 传过来的对象就是一个bean
    // 在初始化调用方法之前做一个后置处理工作
    // 什么时候调用它:  在init-method=init 之前调用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitializationv ...."+beanName+"......>"+bean);
​
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization ...."+beanName+"......>"+bean);
​
        return bean;
    }
}

6 ,使用BeanPostProcessors 源码初步分析

1,postProcessBeforeInitialization

2,postProcessAfterInitialization

原密码

1.AnnotationConfigApplicationContext

2,this.refresh(); // 刷新并创建容器

3,this.finishBeanFactoryInitialization(beanFactory);

4,beanFactory.preInstantiateSingletons(); // 实例化单实例的bean

5,getBean(beanName);

6,return doGetBean(name, null, null, false);

7,sharedInstance = getSingleton(beanName, () -> {

【return createBean(beanName, mbd, args);】

8,singletonObject = singletonFactory.getObject();

8,Object beanInstance = doCreateBean(beanName, mbdToUse, args);

9,instanceWrapper = createBeanInstance(beanName, mbd, args); // 创建bean

populateBean(beanName, mbd, instanceWrapper); // 创建完bean 之后给属性赋值

exposedObject = initializeBean(beanName, exposedObject, mbd); 再到bean 的初始化

10, invokeInitMethods(beanName, wrappedBean, mbd);

11,((InitializingBean) bean).afterPropertiesSet();

只要使用了 @注解就是一个增强

第四课

贯穿我们的bean 离不开我们的BeanPostProcessor 接口 无非就是对他的实现

对于我们的注解来说

Autowird ---->来说起作用的是整个AutowiredAnnotationBeanPostProcessor 后置处理器; 整个其实也是一个bean 只不过可以控制我们的bean,AutowiredAnnotationBeanPostProcessor 也会注册到IOC 容器中

applyBeanPostProcessorsBeforeInitialization(“Jeep”, beanName);

for (把我们Spring所有的processor 进行遍历){

AutowiredAnnotationBeanPostProcessor

}

bean 在运行时期才可以在到他的类型

for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

@Transactional // 对方法前做一个事务的声明 然后方法后做一个事务提交,做一个切面的处理

@Transactional

method(){}

异步:

AJAX

@Async // 加注解之后 先打印syso(“test 被执行了”) 然就在syso(“被执行了。。。”)

public A(){

syso(“被执行了。。。”)

sleep();

}

public test(){

A()

syso(“test 被执行了”)

}

正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

@Autowired @Service @Inject

@Quialifar @Primary

2 @Value 属性赋值

1,使用bean.xml 配置文件进行赋值

2, 使用@Value 赋值 : 基本字符赋值, Spring表达式赋值,获取运行环境变量的值;

3, 使用@ Value 从, *properties 取值;

bean.xml ----> location="classpath:/*.properties"

beans.xml -->property="url" value="${}"

@Value 无非就这三种方式

3,@Autowied @Qualifier @Primary 自动装配

什么是自动装配?

spring利用依赖注入(DI),完成对IOC 容器中的各个组件的依赖关系赋值

思考与操作?

1,bean组件加载优先级?

先加载@Autowired 声明的,如果有Qualifier 就去加载指定的Qualifier的bean

2,如果容器中存在两个id相同的bean,会加载那个bean呢?

会覆盖掉前面的 优先加载配置的,然后才扫描包,如果DefaultListableBeanFactory类中,有个属性 allowBeanDefinitionOverriding, 设置为false ,有两个相同id的bean的话就会报错。

3,如何指定装配组件ID进行加载?@Qualifier

@Qualifier("testDao")  //  会指定去容器中拿 testDao 这个id的bean
​

4, 容器加载不存在的bean会出现什么问题?

报错

5,@primary 注解 bean首选如何使用?

@primary 作为首选的,主要的,指定优先级,如果有的话 我先去拿

Spring自动转配的时候默认首选的bean

6,@Autowired @Resource @Inject 区别?

@Autowired @Resource 效果一样的装配bean

@Resource 1,不支持@primary ;2,不支持Autowired false ;3 可能会出现问题; Autowired 有优先级和一些配置更加灵活

@Autowired 用的最多的地方是 controller 层 service 层 dao层

// 可以完成我们的bean 装配

@Inject 她是第三方的一个包 需要引入pom.xml 依赖

也是一个 JSR-330 的一个规范 首先和@Autowired 功能差不多,

支持@primary ,只是没有Autowired 的@Autowired(required = false) 这个是不存在的时候不会报错;

@Inject 使用场景: 有些不是spring项目 可以引入这个包 然后使用注入方式

@Service
public class TestService {

    //@Qualifier("testDao")
    @Autowired(required = false)
   // @Inject
   //@Resource
    private TestDao testDao;
    public void println(){
        System.out.println(testDao);

    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值