Spring注解驱动IOC篇

给容器中注册组件:

1、        包扫描+组件标注注解(@Contorller @Service @Repository @Component)

2、        @Bean[导入第三方包里面的组件]

3、        @Import[快速给容器中导入一个组件]

4、        @ImportSelector:返回需要导入的组件的全类名

5、        @ImportBeanDefinitRegistrar:通过调用beanDefinitionRegistry.registerBeanDefinition()方法

6、        使用spring提供的FactoryBean注册Bean


@Bean注解

Pom.xml加入context包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

 

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

创建一个javaBean

public class Persion {
    private String userName;
    private String age;
    private String sex;

    get set …

创建一个配置类

@Configuration //告诉spring这是一个配置类
  public class MainConfig {
    @Bean("persion")  //给容器中注册一个Bean,类型为返回值类型 ,用方法名作Id
    public Persion persion(){
        return new Persion("lisi","20","男");
    }
}

加载输出

public class Main {
    public static void main(String[] args) {
        //将配置类传入进来
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Persion bean = applicationContext.getBean(Persion.class);
        System.out.println(bean);
        //获取persion的方法名
        String[] namesForType = applicationContext.getBeanNamesForType(Persion.class);
        for (String name:namesForType){
            System.out.println(name);
        }
    }
}
输出结果:Persion{userName='lisi', age='20', sex='男'}
persion
 
@ComponentScan

@Configuration //告诉spring这是一个配置类
@ComponentScan(value = "com.jbit")
public class MainConfig {
    @Bean("persion")  //给容器中注册一个Bean,类型为返回值类型 ,IDe用方法名作Id
    public Persion persion(){
        return new Persion("lisi","20","男");
    }
}

@Controller
public class BookController {
}

@Repository
public class BookDao {
}

@Service
public class BookService {
}

public class IOCtest {
    @SuppressWarnings("resource")
    @Test
    public void test1(){
      AnnotationConfigApplicationContext applicationContext =  new AnnotationConfigApplicationContext(MainConfig.class);
        //查看组件
        String[] definitionName = applicationContext.getBeanDefinitionNames();
        for(String name:definitionName){
            System.out.println(name);
        }
    }
}

输出结果:

mainConfig

bookController

bookDao

bookService

persion

 

//根据配置条件排除要扫描的包
@ComponentScan(value = "com.jbit",excludeFilters =
        {@ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class, Service.class})})

输出结果:

mainConfig

bookController

bookDao

bookService

persion

//根据配置条件指定要扫描的包,useDefaultFilters = false清除默认设置
@ComponentScan(value = "com.jbit",includeFilters =
        {@ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class, Service.class})},useDefaultFilters = false)

输出结果:

mainConfig

bookController

bookService

persion

注:@ComponentScans中可以配置多个扫描策略!

根据自定义规则扫描

@Configuration //告诉spring这是一个配置类
//根据自定就规则扫描
@ComponentScan(value = "com.jbit",includeFilters =
                @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class}))
//ANNOTATION,按照注解
//ASSIGNABLE_TYPE,按照类型
//ASPECTJ,表达式
//REGEX,正则表达式
//CUSTOM;自定义规则
public class MainConfig {
    @Bean("persion")  //给容器中注册一个Bean,类型为返回值类型 ,IDe用方法名作Id
    public Persion persion(){
        return new Persion("lisi","20","男");
    }
}

 

自定义规则扫描配置类

//自定义规则扫描
//metadataReader:读取当前正在扫描的类的信息
//MetadataReaderFactory:可以获取到其它任何类的信息
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类的加载资源(类的路径)
        Resource resource = metadataReader.getResource();
        System.out.println("======>" + classMetadata.getClassName());
        //如果类中包含er就会被扫描到
        if (classMetadata.getClassName().contains("er")) {
            return true;
        }
        return false;
    }
}

输出结果:

======>com.jbit.test.IOCtest

======>com.jbit.config.MyTypeFilter

======>com.jbit.main.Main

======>com.jbit.pojo.Persion

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalRequiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

org.springframework.context.event.internalEventListenerProcessor

org.springframework.context.event.internalEventListenerFactory

mainConfig

myTypeFilter

bookController

bookDao

persion

bookService

 

@Scope

@Configuration //告诉spring这是一个配置类
@ComponentScan("com.jbit")
public class MainConfig {
    @Bean("persion")  //给容器中注册一个Bean,类型为返回值类型 ,用方法名作Id
    public Persion persion(){
        return new Persion("lisi","20","男");
    }
}

@Configuration //告诉spring这是一个配置类
public class MainConfig2 {
    /**
     * prototype(多实例的)
     * singleton(单实例的)
     * request(同一个请求)
     * session(同一个会话)
     */
    //默认是单实例的
    @Scope("prototype")
    @Bean("persion")  //给容器中注册一个Bean,类型为返回值类型 ,用方法名作Id
    public Persion persion(){
        return new Persion("zhansan","22","男");
    }
}

@Test
public void test1() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    Object bean = applicationContext.getBean("persion");
    Object bean1 = applicationContext.getBean("persion");
    //两个bean默认是相等的
    //在加上@Scope("prototype")注解后是false
    System.out.println(bean == bean1);

如果是单实例,ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是直接加从容器(map.get())中拿。

如果是多实例ioc容器并不会去调用方法创建对象放在容器中,每次获取方法的时候都会调用对象。
}

 

@Lazy (针对单实例)

懒加载:单实例bean,默认在容器启动的时候创建对象,懒加载,容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化。

@Configuration
public class MainConfig2 {
    @Lazy
    @Bean("persion")
    public Persion persion(){
        return new Persion("zhansan","22","男");
    }
}

 

@Conditional

按照一定的条件进行判断,满足条件给容器中注册Bean

@Bean("bill")
public Persion persion01(){
    return  new Persion("Bill Gates","62","男");
}
@Bean("liues")
public Persion persion02(){
    return  new Persion("liues","48","男");
}


@Test
public void test2() {
   String[] getNamesType =  applicationContext.getBeanNamesForType(Persion.class);
    for (String name : getNamesType){
        System.out.println(name);
    }
    Map<String,Persion> persionMap = applicationContext.getBeansOfType(Persion.class);
    System.out.println(persionMap);
}

输出结果:

persion

bill

liues

{persion=Persion{userName='zhansan', age='22', sex='男'}, bill=Persion{userName='Bill Gates', age='62', sex='男'}, liues=Persion{userName='liues', age='48', sex='男'}}

如果系统是windows容器中放入bill,如果是linux就给容器中放入linus

//判断系统是否是linux
public class LinuxCondition implements Condition {
    /**
     * @param conditionContext      :判断条件能使用的上下文条件
     * @param annotatedTypeMetadata :注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //是否linux系统
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取是否是类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取Bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        String propertity = environment.getProperty("os.name");
        if (propertity.contains("Linux")) {
            return true;
        }
        return false;
    }
}

//判断系统是否是windows
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        String propertity = environment.getProperty("os.name");
        if (propertity.contains("Windows")) {
            return true;
        }
        return false;
    }
}

@Conditional({WindowsCondition.class})
@Bean("bill")
public Persion persion01(){
    return  new Persion("Bill Gates","62","男");
}

@Conditional({LinuxCondition.class})
@Bean("liues")
public Persion persion02(){
    return  new Persion("liues","48","男");
}

@Test
public void test2() {
    //获取当前系统运行环境
    ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
    //动态获取系统环境变量的值,windows10
    String propertity = configurableEnvironment.getProperty("os.name");
    System.out.println(propertity);
    String[] getNamesType = applicationContext.getBeanNamesForType(Persion.class);
    for (String name : getNamesType) {
        System.out.println(name);
    }
    Map<String, Persion> persionMap = applicationContext.getBeansOfType(Persion.class);
    System.out.println(persionMap);
}

输出结果:

Windows 10

persion

bill

{persion=Persion{userName='zhansan', age='22', sex='男'}, bill=Persion{userName='Bill Gates', age='62', sex='男'}}

//判断容器中是否包某一个Bean,也可以给容器中注册一个Bean
boolean defin =  registry.containsBeanDefinition("persion");

 

如果将Conditional({WindowsCondition.class})放在类上,那么就味着,只要满足条件这个类中的Bean就会生效。

注:改变系统配置在Run Vm arguments下加入-Dos.name=linux

 

@Import

public class Color {
}

public class Red {
}
@Import({Color.class,Red.class})//@Import导入组件,id默认的是全类名
  public class MainConfig2 {
    @Lazy
    @Bean("persion")
    public Persion persion(){
        return new Persion("zhansan","22","男");
    }
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Persion persion01(){
        return  new Persion("Bill Gates","62","男");
    }
}
@Test
  public void testImport(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    printBean(applicationContext);
}
  private void printBean(AnnotationConfigApplicationContext applicationContext){
    String[] names = applicationContext.getBeanDefinitionNames();
    for(String name:names){
        System.out.println(name);
    }
}
输出结果:
mainConfig2
com.jbit.pojo.Color
com.jbit.pojo.Red
persion
bill

 

@ImportSelector

//定义一个Blue类
public class Blue {
}
//自定义逻辑返回需要导入的组件
  public class MyImportSelector implements ImportSelector {
    //返回值就是到导入到容器中的组件全类名
    //annotationMetadata:当前标注@Import注解类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //方法不能返回null,可以返回空数组
        return new String[]{"com.jbit.pojo.Blue"};
    }
}
//将MyImportSelector类加到@Import中
@Import({Color.class,Red.class,MyImportSelector.class})//@Import导入组件,id默认的是全类名
  public class MainConfig2 {

}

//测试

@Test
  public void testImport() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    printBean(applicationContext);
    Blue bean = applicationContext.getBean(Blue.class);
    System.out.println(bean);
}
  
  private void printBean(AnnotationConfigApplicationContext applicationContext) {
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}
输出结果:
mainConfig2
com.jbit.pojo.Color
com.jbit.pojo.Red
com.jbit.pojo.Blue
persion
bill
com.jbit.pojo.Blue@78047b92

 

//定义一个RainBow类
public class RainBow {
}
//创建一个MyBeanDefinitionRegistrar类实现ImportBeanDefinitionRegistrar
public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
       * @param annotationMetadata:当前类的注解信息
     * @param beanDefinitionRegistry:beanDefinition注册类 把所有需要添加到容器中的bean,调用beanDefinitionRegistry.registerBeanDefinition手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        boolean definition = beanDefinitionRegistry.containsBeanDefinition("com.jbit.pojo.Red");
        boolean definition1 = beanDefinitionRegistry.containsBeanDefinition("com.jbit.pojo.Blue");
        //如果有条件为true,就注册一个RainBow的Bean到ioc容器中
        if (definition && definition1) {
            //指定一个bean名
            RootBeanDefinition rootBean = new RootBeanDefinition(RainBow.class);
            //注册一个Bean
            beanDefinitionRegistry.registerBeanDefinition("rainBow",rootBean);
        }
    }
}
//将MyBeanDefinitionRegistrar类放入到@Import中
@Import({Color.class,Red.class,
        MyImportSelector.class,MyBeanDefinitionRegistrar.class})//@Import导入组件,id默认的是全类名
  public class MainConfig2 {
 
//测试
@Test
  public void testImport() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    printBean(applicationContext);
    Blue bean = applicationContext.getBean(Blue.class);
    System.out.println(bean);
}
  
  private void printBean(AnnotationConfigApplicationContext applicationContext) {
    String[] names = applicationContext.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}
输出结果:
mainConfig2
com.jbit.pojo.Color
com.jbit.pojo.Red
com.jbit.pojo.Blue
persion
bill
rainBow
com.jbit.pojo.Blue@1460a8c0

 

 

使用FactoryBean注册Bean

public class Color {
}

public class FactoryColor implements FactoryBean<Color> {
    @Override
    public Color getObject() throws Exception {
        return  new Color();
    }
    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }
    @Override
    public boolean isSingleton() {
        return false;
    }
}

@Bean
public FactoryColor factoryColor() {
    return new FactoryColor();
}

@Test
public void testFactory(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    Object bean = applicationContext.getBean("factoryColor");
    System.out.println(bean.getClass());
    System.out.println("======================================");
    Object bean1 = applicationContext.getBean("&factoryColor");
    System.out.println(bean1.getClass());
}

输出结果:

class com.jbit.pojo.Color

======================================

class com.jbit.config.FactoryColor

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值