spring常用注解与IOC知识


一 常用配置类

1.@Bean和@Configuration

@Bean用来给容器注入一个组件。默认为单实例,可通过@Scope修改
@Configuartion标注这是一个配置类。

1.1 基本使用

写一个配置类

@Configuration
public class personConfig {
    //方法名作为bean的ID,配置的在容器中的person的ID为:person01
    @Bean
    public person person01()
    {
        return new person("12","Czy");
    }
}

要注入容器中的类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class person {
    public  String age;
    public  String name;
}

打印获取的类

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class MainApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person01");
        //查看Bean的类型
        System.out.println("id为person01的Bean类型为------>" + person.getClass());
        //打印获取到的数据
        System.out.println(person);
    }
}

输出为:

id为person的Bean类型为------>class com.czy.Entity.person
person(age=12, name=Czy)

1.2 改变注入容器中的Bean的ID值

一般情况下,方法名为bean的ID值,如在@Bean直接添加(value=”__“),则可以改变Bean的ID值
例如做出如下改动

@Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }

则person在容器中的ID值会改为person02

2.@ComponentScan

给配置类加上@ComponentScan,其中value值为包的路径,配置类会自动将该包下的标注了诸如(@Controller,@Autowired,@Service,@Repository,@Compoent)的类自动转注进容器中。

2.1 具体用法

项目的目录结构如下,Controller包和Service包下的都添加了注解
在这里插入图片描述

配置类添加注解@ComponentScan

@Configuration
@ComponentScan("com.czy")
public class personConfig {
    
    @Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }
}

获取到的bean如下:(可见标注了@Controller,@Autowired,@Service,@Repository,@Compoent已经自动注入到容器中)

当前获取到的bean的ID为personConfig
当前获取到的bean的ID为peroController
当前获取到的bean的ID为mainApplication
当前获取到的bean的ID为personService

2.2 @ComponentScan深入使用

①扫描时排除注解标注的类
	Filter[] excludeFilters() default {};

具体设置代码如下

/*
		 * type:指定你要排除的规则,FilterType.ANNOTATION按照注解进行排除
		 * classes:除了@Controller和@Service标注的组件之外,IOC容器中剩下的组件我都要,即相当于是我要排除@Controller和@Service这俩注解标注的组件。
		 */
		@Filter(type=FilterType.ANNOTATION, classes={Controller.class, Service.class})
		

FilterType 有如下几种方式

public enum FilterType {

	/**
	 * Filter candidates marked with a given annotation.
	 * @see org.springframework.core.type.filter.AnnotationTypeFilter
	 */
	ANNOTATION,

	/**
	 * Filter candidates assignable to a given type.
	 * @see org.springframework.core.type.filter.AssignableTypeFilter
	 */
	ASSIGNABLE_TYPE,

	/**
	 * Filter candidates matching a given AspectJ type pattern expression.
	 * @see org.springframework.core.type.filter.AspectJTypeFilter
	 */
	ASPECTJ,

	/**
	 * Filter candidates matching a given regex pattern.
	 * @see org.springframework.core.type.filter.RegexPatternTypeFilter
	 */
	REGEX,

	/** Filter candidates using a given custom
	 * {@link org.springframework.core.type.filter.TypeFilter} implementation.
	 */
	CUSTOM

}

FilterType 取ASSIGNABLE_TYPE的话,扫描Entity下的类时,该类不需要加@Component就可以向容器中注入。
如果不取 ASSIGNABLE_TYPE的话,则只能
如下代码,Snake不需要加@Component就能注入到容器中

@Configuration
@ComponentScan(value="com.czy.Entity",includeFilters = {@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,classes= {Snake.class, MyBeanPostProcessor.class})},useDefaultFilters = false)
public class personConfig {


    @Scope("prototype")
    @Bean(value="person02",initMethod = "init",destroyMethod = "destory")
    public person person01()
    {
        return new person("12","Czy");
    }

}
② 扫描时只扫描包含注解标注的类
Filter[] includeFilters() default {};
@ComponentScan(value="com.czy", excludeFilters={
		/*
		 * type:指定你要排除的规则,FilterType.ANNOTATION按照注解进行排除
		 * classes:除了@Controller和@Service标注的组件之外,IOC容器中剩下的组件我都要,即相当于是我要排除@Controller和@Service这俩注解标注的组件。
		 * useDefaultFilters需要设置为false,才可以根据自己的设定进行扫描
		 */
		@Filter(type=FilterType.ANNOTATION, classes={Controller.class, Service.class})
}, useDefaultFilters=false)
③ 自定义过滤规则

要实现自定义规则进行过滤时,自定义规则的类必须是org.springframework.core.type.filter.TypeFilter接口的实现类。
具体代码实现如下:
自己写一个实现类实现org.springframework.core.type.filter.TypeFilter接口。
以下代码将类名中含有Service的类加入容器中,其他的类不加入容器。

public class FilterImplement  implements TypeFilter {


        /**
         * 参数:
         * metadataReader:读取到的当前正在扫描的类的信息
         * metadataReaderFactory:可以获取到其他任何类的信息的(工厂)
         * 返回值为True则成功,否则失败:失败不会加入容器中,成功才加入容器
         */
        @Override
        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("Service"))
            return true;
            return  false;
        }
}

则输出结果只有:

当前获取到的bean的ID为personConfig//配置类
当前获取到的bean的ID为personService//通过自定义过滤器添加的组件
当前获取到的bean的ID为person02//通过Bean添加的组件

3.@Scope

@Scope用于设置Bean的创建方式:单实例/多实例
源码如下:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

	/**
	 * Alias for {@link #scopeName}.
	 * @see #scopeName
	 */
	@AliasFor("scopeName")
	String value() default "";

	/**
	 * Specifies the name of the scope to use for the annotated component/bean.
	 * <p>Defaults to an empty string ({@code ""}) which implies
	 * {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
	 * @since 4.2
	 * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
	 * @see ConfigurableBeanFactory#SCOPE_SINGLETON
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
	 * @see #value
	 */
	@AliasFor("value")
	String scopeName() default "";

	/**
	 * Specifies whether a component should be configured as a scoped proxy
	 * and if so, whether the proxy should be interface-based or subclass-based.
	 * <p>Defaults to {@link ScopedProxyMode#DEFAULT}, which typically indicates
	 * that no scoped proxy should be created unless a different default
	 * has been configured at the component-scan instruction level.
	 * <p>Analogous to {@code <aop:scoped-proxy/>} support in Spring XML.
	 * @see ScopedProxyMode
	 */
	ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;

}

可知scopeName可以有以下的取值(类名#类中的属性):
①ConfigurableBeanFactory#SCOPE_PROTOTYPE:singleton:单实例的(默认值)
②ConfigurableBeanFactory#SCOPE_SINGLETON:prototype:多实例的
③org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST:request:同一请求创建一个实例
④org.springframework.web.context.WebApplicationContext#SCOPE_SESSION:同一个Session创建一个实例
ConfigurableBeanFactory的部分源码为:
在这里插入图片描述
单实例创建会在Ioc容器启动后自动创建,以后每次获取的bean都会是同一个Bean。
多实例创建则会在getBean方法的时候才回去创建Bean实例,且每次创建的Bean都不一样。
具体使用方法如下:

 @Scope("prototype")
    @Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }

验证:

  public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person02");
        //根据Bean的ID获取,
        person person1=(person) annotationConfigApplicationContext.getBean("person02");
        System.out.println(person == person1);
    }

结果如下:

15:26:28.055 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'personConfig'
15:26:28.060 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'personService'
15:26:28.073 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
false

4.@Lazy

如果想让单实例Bean在初始化容器时不自动创建,而是在获取的时候才创建,可以使用@Lazy。
具体用法如下:在方法上添加

@Configuration
@ComponentScan(value="com.czy",includeFilters = {@ComponentScan.Filter(type= FilterType.CUSTOM,classes= {FilterImplement.class})},useDefaultFilters = false)
public class personConfig {
    @Lazy
   // @Scope("prototype")
    @Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }
}

5.@Conditional

作用:按照一定的条件进行判断,满足添加才给容器中添加注册Bean
@Conditonal的源码如下:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();
}

可知value需要传入实现Condtion接口的类,同时可知它可以标注在
①方法上,则方法要创建Bean需要满足Condtional的条件才行。
②类上,则类要满足Condtional的条件才能实现里面的所有创建Bean的方法。

具体使用代码实现:
实现场景:当系统使用的系统为Windows时,注册Bean,否则不注册
配置类如下:

@Configuration
@ComponentScan(value="com.czy",includeFilters = {@ComponentScan.Filter(type= FilterType.CUSTOM,classes= {FilterImplement.class})},useDefaultFilters = false)
public class personConfig {

    //根据源码,value值填入的类必须实现Condition接口
    @Conditional(value = {Windows.class})
    @Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }
}

从源码可知,@Conditional的条件判断类需要实现Conditon接口,条件判断类返回True则@Condtional条件判断成立:

/**
 * @author czy
 * @create 2021-07-09-16:13
 */
public class Windows implements Condition {

    //返回True,则是当前条件满足,即@Conditional条件满足,否则为不满足@Conditional条件
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println("当前的环境为"+property);
        if(property.contains("Windows"))
        return true;
        else  return  true;
    }
}

最后的结果,可知当前系统为Windows,成功往容器中注入类:
在这里插入图片描述

6.@Import

向Spring容器中注册bean通常有以下几种方式:
①包扫描+给组件标注注解(@Controller、@Servcie、@Repository、@Component),但这种方式比较有局限性,局限于我们自己写的类
②@Bean注解,通常用于导入第三方包中的组件
③@Import注解,快速向Spring容器中导入一个组件
④利用FactoryBean向Spring容器中加入组件

@Import的源码如下:(value可填任意要传入的类)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration @Configuration}, {@link ImportSelector},
	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
	 */
	Class<?>[] value();

}

从源码可看到,@Import 的使用方式有三种使用方式:

①直接在配置类上标注

在这里插入图片描述
打印容器中注册的类

   public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person02");
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name: beanDefinitionNames) {
            System.out.println("获取的组件为"+name);
        }
    }

可知注入到容器中的类的ID是类的全路径
在这里插入图片描述

②利用实现了ImportSelector接口的类

第一步,编写一个实现了ImportSelector接口的类,String[]中编写需要Improt的类

public class ImportSelectorImplement implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{"com.czy.Entity.Dog","com.czy.Entity.Fish"};
    }
}

将下面俩个加进到容器中
在这里插入图片描述
输出结果如下:

在这里插入图片描述

③利用实现了ImportBeanDefinitionRegistrar接口的类

向容器中注入Snake这个类

public class ImportBeanDefinitionRegistrarCzy implements ImportBeanDefinitionRegistrar {
    /**
     * AnnotationMetadata:当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     *
     * 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Snake.class);
        registry.registerBeanDefinition("Snake", beanDefinition);
    }
}

在这里插入图片描述

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
public class MainApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person02");
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name: beanDefinitionNames) {
            System.out.println("获取的组件为"+name);
        }
    }
}

输出结果如下:
在这里插入图片描述

④使用FactoryBean向Spring容器中注册bean

写一个FactoryBean的实现类,类中的泛型填写要注册的Bean的类

public class FactoryBeanImpl implements FactoryBean<Mouse> {

    //返回由FactoryBean创建的bean实例,如果isSingleton()返回true,那么该实例会放到Spring容器中单实例缓存池中
    @Override
    public Mouse getObject() throws Exception {
        System.out.println("正在创建Mouse");
        return new Mouse();
    }

    //返回FactoryBean创建的bean实例的类型
    @Override
    public Class<?> getObjectType() {
        return Mouse.class;
    }

    //返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
    @Override
    public boolean isSingleton() {
        return false;
    }

}

在配置类注册工厂实现类

@Import({Dog.class,ImportSelectorImplement.class,ImportBeanDefinitionRegistrarCzy.class})
@Configuration
public class personConfig {
    //根据源码,value值填入的类必须实现Condition接口
    @Conditional(value = {Windows.class})
    @Bean("person02")
    public person person01()
    {
        return new person("12","Czy");
    }


    //注入
    @Bean
    public FactoryBeanImpl FactoryBeanImpl() {
        return new FactoryBeanImpl();
    }
}

打印Bean:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
public class MainApplication {
public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person02");
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name: beanDefinitionNames) {
            System.out.println("获取的组件为"+name);
        }

        // 工厂bean获取的是调用getObject方法创建的对象
        Object bean2 = annotationConfigApplicationContext.getBean("FactoryBeanImpl");
        Object bean3 = annotationConfigApplicationContext.getBean("FactoryBeanImpl");
        System.out.println("获取的工厂bean的类型:" + bean2.getClass());
        System.out.println(bean2==bean3);
    }
}
获取的组件为personConfig
获取的组件为com.czy.Entity.Dog
获取的组件为com.czy.Entity.Fish
获取的组件为person02
获取的组件为FactoryBeanImpl
获取的组件为Snake
正在创建Mouse
正在创建Mouse
获取的工厂bean的类型:class com.czy.Entity.Mouse
false

可知代码中getbean的填入的是工厂实现类,但是实际获取的是时候会调用getObject方法所创建的对象,即工厂实现类向容器中注册的类。且由于在工厂实现类中填写的isSingleton为false,所以每次获取Bean的时候都会创建一个Bean。
如果向获取工厂实现类,应当以这种写法:

 Object bean4 = annotationConfigApplicationContext.getBean("&FactoryBeanImpl");

7.@Value

作用:赋予类的初值。
用法:
①直接赋值 ②数学表示式{#数学表达式}

@Value("#{25-1}")
    public  Integer age;
    @Value("czy")
    public  String name;

③取配置文件的值(${})需要结合@PropertySource使用

8.@PropertySource

@PropertySource用来给配置类指定配置文件的路径
@PropertySource的源码:
箭头所指为它的value的书写方式,指出配置文件的位置
箭头所指为它的value的书写方式,指出配置文件的位置
配置文件:下为配置文件目录和内容
在这里插入图片描述
配置类需要指出从哪个配置文件中取值
在这里插入图片描述

9.@Autowired

@Autowired:按类型获取Bean ,的作用等价于

applicationContext.getBean(类名.class);

如果找到多个相同类型的组件,那么是将属性名称作为组件的id,到IOC容器中进行查找,这时就相当于是调用了如下这个方法:
applicationContext.getBean(“组件的id”);
@Autowired(required = false):当注入类在容器中找不到时不会报错,会赋值为空
@Autowired可用在:
①属性,用法如上
②方法上,用法:

 @Autowired
        //在方法上使用@Autowired,会在该类的初始化的时候便调用该方法,从容器中取得该Bean,调用赋值。
    public void setBee(Bee bee)
        {
            this.bee=bee;
        }

③构造器上,用法:
在默认情况下会使用无参构造器,可用 @Autowired标注在构造器上,可调用 @Autowired标注的构造器

@Autowired
    public person(Bee bee){
        this.bee=bee;
    }

④放参数上,等同于从容器中获取bean

public person(@Autowired Bee bee){
        this.bee=bee;
    }

此代码与上面的代码功能一致,都是在初始化的时候进行属性的赋值。
如果只有一个参数,则@Autowired 可省略,直接从容器中拿。
普遍用发:@Bean 然后在参数上使用@Autowired获得参数,默认不写

10.@Qualifier和@Primary

@Qualifier(“组件的id值”)== 寻找指定的id的组件
场景:一个类可能有多个注入bean到容器中,但是bean值不同,可用@Qualifier区分
@Primary(”“组件的id值)== 首先用primary注解注释的组件,需要在Qualifier不启动的状态下使用

11.@Resource和@Inject

@Resource和@Inject是由java提供的,与@Autowired提供的能够基本相同。
@Resource注解中的方法:(name=”“)可以自己指定需要的类,不可与@Qualifier和@Primary(spring框架)等使用,@Inject则可以

二 Bean的生命周期

创建→初始化→销魂

1.在@Bean指定初始化和销毁的方法

在person类中添加方法:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class person {
    public  String age;
    public  String name;
    public void init()
    {
        System.out.println("创建person++++++");
    }
    public void destory()
    {
        System.out.println("毁坏person+++++++++++");    }
}

在配置类中注入person的时候,在@Bean中添加初始化和销毁的方法

在这里插入图片描述
通过打印查看bean的生命周期

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
public class MainApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        System.out.println("创建容器完成");
        //根据Bean的ID获取,
        person person=(person) annotationConfigApplicationContext.getBean("person02");
        System.out.println(person);
        annotationConfigApplicationContext.close();
    }
}

由图可知在容器创建后,便会执行Bean的初始化方法,而在容器关闭的时候,容器也会执行Bean的销毁方法。这种情况是在单实例的情况下
在这里插入图片描述
如果设置为多实例:
在这里插入图片描述
输出结果如下:
在这里插入图片描述
可知bean在多实例情况下,容器不会一开始就执行Bean的创建方法,只有在getBean的时候才会创建Bean,进而执行Bean的Init方法,且在容器关闭的时候也不会执行Bean的销毁方法。
总结:
单实例:在容器启动的时候创建对象,容器关闭的时候销毁对象
多实例:在获取Bean的时候创建对象,容器关闭的时候不会销毁对象

2.让Bean实现spring提供的InitializingBean接口和DisposableBean接口

InitializingBean接口和DisposableBean接口是spring为了管理Bean所设计的接口
InitializingBean:在初始化的时候执行里面的方法
DisposableBean:在销毁的时候执行里面的方法
创建一个Bear类,实现这两个接口即可实现初始化和销毁的功能。

public class Bear implements InitializingBean, DisposableBean {
    public Bear() {
        System.out.println("Bear constructor...");
    }
    //销毁Bean执行的方法
    @Override
    public void destroy() throws Exception {
        System.out.println("Bear destroy...");
    }
    //创建Bean执行的方法(在初始化构造器之后)
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Bear afterPropertiesSet...");
    }
}

3.让Bean实现JDK提供的@PostConstruct注解和@PreDestroy注解

被@PostConstruct注解修饰的方法通常在构造函数之后,init()方法之前执行。
Constructor(构造方法)→@Autowired(依赖注入)→@PostConstruct(注释的方法)
被@PreDestroy注解修饰的类销毁执行的流程:调用destroy()方法:@PreDestroy→destroy()方法→bean销毁

@PostConstruct源码如下:

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

@PreDestroy 源码如下:

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

可知两个注解都是作用在方法上的。具体使用:

public class Bee {
    @PostConstruct
    public void init()
    {
        System.out.println("创建++++++");
    }
    @PreDestroy
    public void destory()
    {
        System.out.println("毁坏+++++++++++");    }
}

4.让Bean实现BeanPostProcessor 接口

源码如下:
在这里插入图片描述
其中有两个方法,postProcessBeforeInitialization用于Bean初始化之前做的一些工作
流程:构造函数→postProcessBeforeInitialization→InitializingBean方法→postProcessAfterInitialization
postProcessAfterInitialization用于Bean初始化之后做的一些工作
代码:
配置类:

@Configuration
@ComponentScan(value="com.czy.Entity")
public class personConfig {
}

@Component
public class Snake {
 public Snake()
    {
        System.out.println("snake");
    }
}

自定义的BeanPostProcessor 实现类

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
           System.out.println("自定义的postProcessBeforeInitialization..." + beanName + "=>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("自定义的postProcessAfterInitialization..." + beanName + "=>" + bean);
        return bean;
    }

}

输出结果:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
public class MainApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(personConfig.class);
        System.out.println("创建容器完成");
        //根据Bean的ID获取,
        Object Object=annotationConfigApplicationContext.getBean("snake");
        System.out.println(Object);
        annotationConfigApplicationContext.close();
    }
}

在这里插入图片描述
可知执行的顺序是:先初始化构造器→执行postProcessBeforeInitialization方法→执行postProcessAfterInitialization方法
可以看出getBean填入的应当是类的小写。

三 获取spring中的组件

自定义的组件要想使用Spring容器底层的一些组件,比如ApplicationContext(IOC容器)、底层的BeanFactory等等,那么只需要让自定义组件实现XxxAware接口即可。此时,Spring在创建对象的时候,会调用XxxAware接口中定义的方法注入相关的组件。把spring底层的bean注入到自定义bean中。
以下是实现了Aware接口的类:
在这里插入图片描述
实现原理:根据前面所学,ApplicationContextAwareProcessor在ApplicationContext初始化后注入到容器前先执行,它会先检查容器中有无实现ApplicationContextAware的自定义类,然后给这些自定义类返回容器中的ApplicationContext(单例设计)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值