• Spring注解驱动开发(一)-----组件注册


    注册bean

    xml方式

    1、beans.xml-----很简单,里面注册了一个person bean

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    
        <bean id="person" class="com.atguigu.bean.Person">
            <property name="age" value="18"></property>
            <property name="name" value="zhangsan"></property>
        </bean>
    </beans>

    2、person

    package com.atguigu.bean;
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class Person {
    private String name;
    private Integer age;
       public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        
        public Person(String name, Integer age) {
            super();
            this.name = name;
            this.age = age;
        }
        public Person() {
            super();
        }
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", nickName=" + nickName + "]";
        }
    }

    3、MainTest-----测试类

    package com.atguigu;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.atguigu.bean.Person;
    import com.atguigu.config.MainConfig;
    
    public class MainTest {
        
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            Person bean = (Person) applicationContext.getBean("person");
            System.out.println(bean);
    }

    测试结果:

    注解方式

     1、MainConfig-----配置类

    @Configuration  //告诉Spring这是一个配置类
        //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
        @Bean("person")
        public Person person01(){
            return new Person("lisi", 20);
        }
    }

    2、MainTest

    package com.atguigu;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.atguigu.bean.Person;
    import com.atguigu.config.MainConfig;
    
    public class MainTest {
        
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
            
            String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
            for (String name : namesForType) {
                System.out.println(name);
            }
        }
    }

    3、@Configuration-----可以看出是继承了@Component

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Configuration {
        @AliasFor(annotation = Component.class)
        String value() default "";
    
    }

    自动扫描

    xml方式 

    1、beans.xml 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
        <context:component-scan base-package="com.atguigu"></context:component-scan>
        <bean id="person" class="com.atguigu.bean.Person">
            <property name="age" value="18"></property>
            <property name="name" value="zhangsan"></property>
        </bean>
    </beans>

    注解方式

    1、MainConfig

    package com.atguigu.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.ComponentScans;
    
    import com.atguigu.bean.Person;
    
    //配置类==配置文件
    @Configuration  //告诉Spring这是一个配置类
    @ComponentScan(value="com.atguigu")  //value:指定要扫描的包
    public class MainConfig {    
        //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
        @Bean("person")
        public Person person01(){
            return new Person("lisi", 20);
        }
    
    }

    2、BookController

    package com.atguigu.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    import com.atguigu.service.BookService;
    
    @Controller
    public class BookController {
        
        @Autowired
        private BookService bookService;
    
    }

    3、BookService

    package com.atguigu.service;
    
    
    import javax.annotation.Resource;
    import javax.inject.Inject;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    import com.atguigu.dao.BookDao;
    
    
    @Service
    public class BookService {
    
        @Autowired(required=false)
        private BookDao bookDao;
        
        public void print(){
            System.out.println(bookDao);
        }
    
        @Override
        public String toString() {
            return "BookService [bookDao=" + bookDao + "]";
        }
    }

    4、BookDao

    package com.atguigu.dao;
    
    import org.springframework.stereotype.Repository;
    
    //名字默认是类名首字母小写
    @Repository
    public class BookDao {
        
        private String lable = "1";
    
        public String getLable() {
            return lable;
        }
    
        public void setLable(String lable) {
            this.lable = lable;
        }
    
        @Override
        public String toString() {
            return "BookDao [lable=" + lable + "]";
        }
    }

    5、IocTest

    package com.atguigu.test;
    
    import java.util.Map;
    
    import org.junit.Test;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.core.env.ConfigurableEnvironment;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Person;
    import com.atguigu.config.MainConfig;
    import com.atguigu.config.MainConfig2;
    
    public class IOCTest {
        
        @SuppressWarnings("resource")
        @Test
        public void test01(){
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            String[] definitionNames = applicationContext.getBeanDefinitionNames();
            for (String name : definitionNames) {
                System.out.println(name);
            }
        }
    }

    @ComponentScan

    1、excludeFilters

    @ComponentScan(value="com.atguigu",excludeFilters = {
                            @Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class}))

    排除controller以及service,不允许注册。

    这里需要注意一个问题,需要使用excludeFilters的时候,use-default-filters需要设置为true或者不设置,因为use-default-filters属性的默认值为true。否则会出现报错的现象,例如无法成功注册相应的bean。原因如下:

    要分析这个错误,就要先了解 use-default-filters 这个属性的作用。use-default-filters 属性的默认值为 true,即使用默认的 Filter 进行包扫描,而默认的 Filter 对标有 @Service,@Controller和@Repository 的注解的类进行扫描而我们只希望 SpringMVC 的配置扫描 @Controllerce 注解标注的类,不希望它扫描其余注解标注的类,所以设置了 use-default-filters 为 false,并使用 context:include-filter 子标签设置其只扫描带有 @Controller 注解标注的类。
    而 Spring 就不同了,我们希望 Spring 只不扫描带有 @Controller 注解标注的类,而扫描其他注解标注的类,而这时建立在使用默认的 Filter 进行扫描的基础上,设置了 context:exclude-filter 标签,不扫描 @Controller 注解标注的类,所以不应该设置 use-default-filters 为 false,所以这就解释了为什么一开始启动 Tomcat 时报了一个找不到 Service 的错误。

    2、includeFilters

    @ComponentScan(value="com.atguigu",includeFilters = {
                            @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),useDefaultFilters=false)

    只扫描controller。-----需要添加useDefaultFilters=false

    @ComponentScans 

    @ComponentScans(
            value = {
                    @ComponentScan(value="com.atguigu",includeFilters = {
                            @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
                    },useDefaultFilters = false)    
            }
            )

    其实就是可以定义多个扫描策略。

    TypeFilter 

    • @ComponentScan value:指定要扫描的包
    • excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
    • includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
    • FilterType.ANNOTATION:按照注解
    • FilterType.ASSIGNABLE_TYPE:按照给定的类型;
    • FilterType.ASPECTJ:使用ASPECTJ表达式
    • FilterType.REGEX:使用正则指定
    • FilterType.CUSTOM:使用自定义规则

    其中注解最为常见。 

    设置组件作用域

    @Scope

     spring中默认都是单例bean,不过也可以通过@Scope进行设置。

    1、MainConfig2

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    @Configuration
    public class MainConfig2 {
        
        //默认是单实例的
        /**
         * ConfigurableBeanFactory#SCOPE_PROTOTYPE    
         * @see ConfigurableBeanFactory#SCOPE_SINGLETON  
         * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST  request
         * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION     sesssion
         * @return
         * @Scope:调整作用域
         * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
         *                     每次获取的时候才会调用方法创建对象;
         * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。
         *             以后每次获取就是直接从容器(map.get())中拿,
         * request:同一次请求创建一个实例
         * session:同一个session创建一个实例
         */
        @Scope("prototype")
        @Bean("person")
        public Person person(){
            System.out.println("给容器中添加Person....");
            return new Person("张三", 25);
        }
    }

    2、IocTest

    package com.atguigu.test;
    
    import java.util.Map;
    
    import org.junit.Test;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.core.env.ConfigurableEnvironment;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Person;
    import com.atguigu.config.MainConfig;
    import com.atguigu.config.MainConfig2;
    
    public class IOCTest {
        
        @Test
        public void test02(){
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
            System.out.println("ioc容器创建完成....");
            Object bean = applicationContext.getBean("person");
            Object bean2 = applicationContext.getBean("person");
            System.out.println(bean == bean2);
        }
    }

    3、测试结果

    @Lazy-----只针对于singleton模式

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    @Configuration
    public class MainConfig2 {
        
        //默认是单实例的
        /**
         * 懒加载:
         *         单实例bean:默认在容器启动的时候创建对象;
         *         懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
         * 
         */
        @Scope("singleton")
        @Lazy
        @Bean("person")
        public Person person(){
            System.out.println("给容器中添加Person....");
            return new Person("张三", 25);
        }
    }

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

    配置在方法上

    示例:根据是windows还是linux系统,判断person为Bill还是Linus

    1、MainConfig

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    @Configuration
    public class MainConfig2 {
    
        /**
         * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
         * 
         * 如果系统是windows,给容器中注册("bill")
         * 如果是linux系统,给容器中注册("linus")
         */
        @Conditional({WindowsCondition.class})
        @Bean("bill")
        public Person person01(){
            return new Person("Bill Gates",62);
        }
        
        @Conditional(LinuxCondition.class)
        @Bean("linus")
        public Person person02(){
            return new Person("linus", 48);
        }
    }

    2、LinuxCondition

    package com.atguigu.condition;
    
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.env.Environment;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    //判断是否linux系统
    public class LinuxCondition implements Condition {
    
        /**
         * ConditionContext:判断条件能使用的上下文(环境)
         * AnnotatedTypeMetadata:注释信息
         */
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // TODO是否linux系统
            //1、能获取到ioc使用的beanfactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //2、获取类加载器
            ClassLoader classLoader = context.getClassLoader();
            //3、获取当前环境信息
            Environment environment = context.getEnvironment();
            //4、获取到bean定义的注册类
            BeanDefinitionRegistry registry = context.getRegistry();
            
            String property = environment.getProperty("os.name");
            
            //可以判断容器中的bean注册情况,也可以给容器中注册bean
            boolean definition = registry.containsBeanDefinition("person");
            if(property.contains("linux")){
                return true;
            }
            
            return false;
        }
    
    }

    3、WindowsCondition

    package com.atguigu.condition;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.env.Environment;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    //判断是否windows系统
    public class WindowsCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            Environment environment = context.getEnvironment();
            String property = environment.getProperty("os.name");
            if(property.contains("Windows")){
                return true;
            }
            return false;
        }
    
    }

    4、IOCTest

    package com.atguigu.test;
    
    import java.util.Map;
    
    import org.junit.Test;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.core.env.ConfigurableEnvironment;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Person;
    import com.atguigu.config.MainConfig;
    import com.atguigu.config.MainConfig2;
    
    public class IOCTest {
        @Test
        public void test03(){
            String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
            ConfigurableEnvironment environment = applicationContext.getEnvironment();
            //动态获取环境变量的值;Windows 10
            String property = environment.getProperty("os.name");
            System.out.println(property);
            for (String name : namesForType) {
                System.out.println(name);
            }
            
            Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
            System.out.println(persons);
            
        }
    }

    运行结果:

    由于当前系统是win10,所以只有Bill对象存在。

    那么如何试验得到Linus呢?

    通过run configuration的-Dos.name,直接更改jvm参数,然后eviroment中取os.name就为linux了。

    配置在类上

    MainConfig

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
    @Conditional({WindowsCondition.class})
    @Configuration
    public class MainConfig2 {
    
        /**
         * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
         * 
         * 如果系统是windows,给容器中注册("bill")
         * 如果是linux系统,给容器中注册("linus")
         */
        
        @Bean("bill")
        public Person person01(){
            return new Person("Bill Gates",62);
        }
        
        @Conditional(LinuxCondition.class)
        @Bean("linus")
        public Person person02(){
            return new Person("linus", 48);
        }
    }

    给容器快速导入一个组件

    给容器注册组件的方式

    1、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
    2、@Bean[导入的第三方包里面的组件]
    3、@Import[快速给容器中导入一个组件]

    • a、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
    • b、ImportSelector:返回需要导入的组件的全类名数组;
    • c、ImportBeanDefinitionRegistrar:手动注册bean到容器中

    4、使用Spring提供的 FactoryBean(工厂Bean);

    • a、默认获取到的是工厂bean调用getObject创建的对象
    • b、要获取工厂Bean本身,我们需要给id前面加一个 && colorFactoryBean

    @Import

    @Configuration
    //@Import导入组件,id默认是组件的全类名
    @Import({Color.class,Red.class})
    public class MainConfig2 {
    
    }

    ImportSelector-----实现这个接口(将需要导入的组件放入数组中)

    1、MyImportSelector

    package com.atguigu.condition;
    
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    
    //自定义逻辑返回需要导入的组件
    public class MyImportSelector implements ImportSelector {
    
        //返回值,就是到导入到容器中的组件全类名
        //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            // TODO Auto-generated method stub
            //importingClassMetadata
            //方法不要返回null值
            return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
        }
    
    }

    2、MainConfig

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    @Configuration
    @Import({MyImportSelector.class})
    public class MainConfig2 {
    
    }

    ImportBeanDefinitionRegistrar-----实现这个接口(创建BeanDefinition,通过BeanDefinitionRegistry.registerBeanDefinition()导入)

    1、MyImportBeanDefinitionRegistrar

    package com.atguigu.condition;
    
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    import com.atguigu.bean.RainBow;
    
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        /**
         * AnnotationMetadata:当前类的注解信息
         * BeanDefinitionRegistry:BeanDefinition注册类;
         *         把所有需要添加到容器中的bean;调用
         *         BeanDefinitionRegistry.registerBeanDefinition手工注册进来
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            
            boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
            boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
            if(definition && definition2){
                //指定Bean定义信息;(Bean的类型,Bean。。。)
                RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
                //注册一个Bean,指定bean名
                registry.registerBeanDefinition("rainBow", beanDefinition);
            }
        }
    
    }

    2、MainConfig2

    package com.atguigu.config;
    
    import org.springframework.context.annotation.Configuration;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    
    @Configuration
    @Import({MyImportBeanDefinitionRegistrar.class})
    //@Import导入组件,id默认是组件的全类名
    public class MainConfig2 {
    
    }

    FactoryBean-----实现spring提供的这个工厂bean

    1、ColorFactoryBean

    package com.atguigu.bean;
    
    import org.springframework.beans.factory.FactoryBean;
    
    //创建一个Spring定义的FactoryBean
    public class ColorFactoryBean implements FactoryBean<Color> {
    
        //返回一个Color对象,这个对象会添加到容器中
        @Override
        public Color getObject() throws Exception {
            // TODO Auto-generated method stub
            System.out.println("ColorFactoryBean...getObject...");
            return new Color();
        }
    
        @Override
        public Class<?> getObjectType() {
            // TODO Auto-generated method stub
            return Color.class;
        }
    
        //是单例?
        //true:这个bean是单实例,在容器中保存一份
        //false:多实例,每次获取都会创建一个新的bean;
        @Override
        public boolean isSingleton() {
            // TODO Auto-generated method stub
            return false;
        }
    
    }

    2、MainConfig2

    package com.atguigu.config;
    
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Scope;
    
    import com.atguigu.bean.Blue;
    import com.atguigu.bean.Color;
    import com.atguigu.bean.ColorFactoryBean;
    import com.atguigu.bean.Person;
    import com.atguigu.bean.Red;
    import com.atguigu.condition.LinuxCondition;
    import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
    import com.atguigu.condition.MyImportSelector;
    import com.atguigu.condition.WindowsCondition;
    import com.atguigu.test.IOCTest;
    
    @Configuration
    public class MainConfig2 {
        /**
         * 给容器中注册组件;
         * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
         * 2)、@Bean[导入的第三方包里面的组件]
         * 3)、@Import[快速给容器中导入一个组件]
         *         1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
         *         2)、ImportSelector:返回需要导入的组件的全类名数组;
         *         3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
         * 4)、使用Spring提供的 FactoryBean(工厂Bean);
         *         1)、默认获取到的是工厂bean调用getObject创建的对象
         *         2)、要获取工厂Bean本身,我们需要给id前面加一个&
         *             &colorFactoryBean
         */
        @Bean
        public ColorFactoryBean colorFactoryBean(){
            return new ColorFactoryBean();
        }
    }

    注:虽然@Bean的是ColorFactoryBean,但是其实是将此工厂内的bean注册到容器中。如果要获取工厂bean本身,getBean("&..."),在名称前加“&”。

    其实也就是说:

    AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
    //获取的是Color对象
    Object bean1 = app.getBean("colorFactoryBean");
    //获取的是ColorFactoryBean工厂对象
    Object bean3 = app.getBean("&colorFactoryBean");
  • 相关阅读:
    CSS3 页面跳转的动画效果
    JS/React 判断对象是否为空对象
    React 根据官方总结的规范
    ckeditor字数限制
    swfobject.js IE兼容问题
    Jcrop 做图片剪裁 在IE中无法显示问题解决办法
    WebApp 中用 hashchange 做路由解析
    全国省市区Json文件 ,做省市区联动很轻松
    解决用友U8删除用户时提示“用户已启用”不能删除的问题
    CFUpdate高速模式下出现Error #2038提示的解决方案
  • 原文地址:https://www.cnblogs.com/alimayun/p/11100414.html
Copyright © 2020-2023  润新知