Spring组件

0.原始注入bean方式

resource下建立beans.xml;

<bean id="car" class="com.peimx.spring.compnent.bean.Car">
    <property name="brand" value="AODI"></property>
    <property name="price" value="18000"></property>
</bean>

方法调用检测

public static void main(String[] args) {
    //上下文注入bean中配置
    ApplicationContext ap = new ClassPathXmlApplicationContext("beans.xml");
    for (String beanDefinitionName : ap.getBeanDefinitionNames()) {//获取bean名称数组
        System.out.println(beanDefinitionName);
    }
    Car car = (Car)ap.getBean("car");//通过id获取bean实例
    System.out.println(car.getBrand());
    System.out.println(car.getPrice());
}

结果输出

car
AODI
18000
    • @Bean方式注入

建立一个配置类

@Configurable
public class MainConfig {

    @Bean("plane") //可直接@Bean,默认取方法名称作为id
    public Plane plane(){
        return new Plane();
    }

}

方法调用检测

 ApplicationContext apps = new AnnotationConfigApplicationContext(MainConfig.class);
        for (String beanDefinitionName : apps.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        Plane plane = (Plane) apps.getBean("plane");
        System.out.println(plane.getBrand());

结果输出

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
plane
null//属性未初始化,所以无值
    • 文件扫描规则@CompnentScan

(0)文件列表

(1)定义范围

bean上加@compent注解

@Component
public class Car extends Transportation {

}

配置文件

@ComponentScan(value = "com.peimx.spring.compnent.bean")
public class MainConfig {

}

结果输出

org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
car
plane
train
null

(2)过滤器

@ComponentScan(value = "com.peimx.spring.compnent",
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION,classes = {Service.class}),//注解方式
                @Filter(type=FilterType.ASSIGNABLE_TYPE,classes = { Train.class}),//指定类型
                @Filter(type=FilterType.CUSTOM,classes = {MyFilter.class}),//自定义过滤器
                @Filter(type=FilterType.ASPECTJ,value = {}),//按照Aspectj的表达式,基本上不会用到
                @Filter(type=FilterType.REGEX,value = {})//正则表达式类型
        },
        useDefaultFilters = true)

此处应注意:useDefaultFilters 默认为true,使用includeFilters条件筛选时,应设为false

其中自定义过滤器

public class MyFilter implements TypeFilter {

    /*
    * metadataReader:读取当前正在扫描类的信息
    * metadataReaderFactory:可以获取到其它任何类的信息
    * */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        System.out.println("--------filter--"+metadataReader.getClassMetadata().getClassName());

        ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类的信息
        AnnotationMetadata annotationMetadata =  metadataReader.getAnnotationMetadata(); //获取当前类注解的信息
        Resource resource =  metadataReader.getResource(); //获取当前路径

        System.out.println(resource.getDescription());
       if(metadataReader.getClassMetadata().getClassName().equals("com.peimx.spring.compnent.bean.Car")){
           return false;
       }
        return true;//true放行,false 拦截
    }

输出结果:

--------filter--com.peimx.spring.compnent.bean.Car
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\bean\Car.class]
--------filter--com.peimx.spring.compnent.bean.Plane
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\bean\Plane.class]
--------filter--com.peimx.spring.compnent.bean.Train
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\bean\Train.class]
--------filter--com.peimx.spring.compnent.bean.Transportation
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\bean\Transportation.class]
--------filter--com.peimx.spring.compnent.config.MyFilter
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\config\MyFilter.class]
--------filter--com.peimx.spring.compnent.controller.CarController
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\controller\CarController.class]
--------filter--com.peimx.spring.compnent.controller.OutPrint
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\controller\OutPrint.class]
--------filter--com.peimx.spring.compnent.dao.CarDao
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\dao\CarDao.class]
--------filter--com.peimx.spring.compnent.service.CarService
file [D:\aStudy\project\spring\target\classes\com\peimx\spring\compnent\service\CarService.class]
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
car //由过滤器可知,只有car返回false,即结果集排除所有只留car

此处小结论:filter之间是并集合关系,也就是说各个过滤器集合合并在一起共同组成过滤器总结果集。

总结:

@ComponentScan(value = "com.peimx.spring.compnent",
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION,classes = {Service.class}),//注解方式
                @Filter(type=FilterType.ASSIGNABLE_TYPE,classes = { Train.class}),//指定类型
                @Filter(type=FilterType.CUSTOM,classes = {MyFilter.class}),//自定义过滤器
                @Filter(type=FilterType.ASPECTJ,value = {}),//按照Aspectj的表达式,基本上不会用到
                @Filter(type=FilterType.REGEX,value = {})//正则表达式类型
        },
        useDefaultFilters = true)
//excludeFilters = Filter[] 指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] 指定扫描的时候只需要包含哪些组件
    • scope扫描规则

配置类

@Configurable
public class MainConfig {
    @Bean("plane")
    @Scope("prototype")
    public Plane plane(){
        return new Plane();
    }

}

方法调用检测

ApplicationContext apps = new AnnotationConfigApplicationContext(MainConfig.class);
        for (String beanDefinitionName : apps.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        Plane plane1 = (Plane) apps.getBean("plane");
        Plane plane2 = (Plane) apps.getBean("plane");
        System.out.println(plane1==plane2);//判断两次取到对象是否相同

结果输出

@Scope("prototype")时,返回false,即每次获取都生成新对象;
@Scope("singleson") 或不配置时,返回true,即同一对象,只实例化一次

结论:

prototype:多实例:IOC容器启动并不会去调用方法创建对象放在容器中,而是 每次获取的时候才会调用方法创建对象,见test02

singleton:单实例(默认):IOC容器启动会调用方法创建对象放到IOC容器中

以后每交获取就是直接从容器(理解成从map.get对象)中拿

request:主要针对WEB应用,同一次请求创建一个实例

session:同一个session创建一个实例(后面两个用得不多,了解即可

    • lazy懒加载

配置类

    @Bean("plane")
    @Lazy
    public Plane plane(){
        System.out.println("给容器添加bean");
        return new Plane();
    }

检测类

 ApplicationContext apps = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("ioc 创建完成");

        Plane plane = (Plane) apps.getBean("plane");

结果

ioc 创建完成
给容器添加bean

结论:单实例默认在容器启动的时候加载对象。懒加载主要针对单实例,容器启动的时候不创建,仅当第一次使用的时候创建和初始化。

    • @Conditional条件注册bean

条件配置

public class WindowsCondition implements Condition {

    /*
    * ConditionContext:判断条件能使用的上下文
    * AnnotatedTypeMetadata:注解信息
    * */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String env = context.getEnvironment().getProperty("os.name");
        if(env.equals("Windows 10")){
            return true; //条件通过
        }
        return false;//条件未通过
    }
}

配置

@Conditional(WindowsCondition.class)
    @Bean("car")
    public Car car(){
        return new Car();
    }

结果

car//满足条件通过打印,若不满足则无结果输出
    • @Import注册bean

自定义配置

(1)注册类

   /*
    * importingClassMetadata : 注解信息
    * registry : BeanDefinition注册类
    * */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
         boolean definition1 = registry.containsBeanDefinition("com.peimx.spring.compnent.bean.Train");//判断是否有train
        if(!definition1){
            RootBeanDefinition beanDefinition =  new RootBeanDefinition(Train.class);
            registry.registerBeanDefinition("train",beanDefinition);
        }
    }

(2)注册类

public class MyImportSelector implements ImportSelector {

    /*
    * AnnotationMetadata 注解信息类
    * */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.peimx.spring.compnent.bean.Car"};
    }
}

配置类

@Configurable
@Import({Plane.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}

结果

com.peimx.spring.compnent.bean.Plane //import注入的id为全路径
com.peimx.spring.compnent.bean.Car
train //注册类自定义名称

7. FactoryBean方式加载bean

配置

     /* 使用spring提供的FactoryBean(工厂bean)
     *   beans.factory.FatoryBean源码跟进去
     *     容器调用getObject()返回对象,把对象放到容器中;
     *     getObjectType()返回对象类型
     *     isSingleton()是否单例进行控制
     *     新建JamesFactoryBean实现FactoryBean
     *     在config里新建jamesFactoryBean()方法
     *     写完测试用例后:
     *       a,默认获取到的是工厂bean调用getObject创建的对象
     *       b,要获取工厂Bean本身,需要在id前加个  &jamesFactoryBean
     */    

public class MyFactoryBean implements FactoryBean<Plane> {
    @Override
    public Plane getObject() throws Exception {
        return new Plane();
    }

    @Override
    public Class<?> getObjectType() {
        return Plane.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

配置类

@Bean
public MyFactoryBean myFactoryBean(){
    return new MyFactoryBean();
}

测试

 ApplicationContext apps = new AnnotationConfigApplicationContext(MainConfig.class);
for (String beanDefinitionName : apps.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
}

Object object = apps.getBean("myFactoryBean");
System.out.println(object.getClass());

结果

mainConfig
myFactoryBean
class com.peimx.spring.compnent.bean.Plane //打印class 可验证已经注入
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值