IOC容器注解汇总,你想要的都在这儿了!!

作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:

专注于为中小企业提供网站建设、成都网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业东乡免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上1000+企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

https://github.com/sunshinelyz/mykit-delay

xml配置与类配置

1.xml配置

获取Person实例如下所示。

 
 
 
 
  1. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/sp
  3.  

2.类配置

 
 
 
 
  1. public static void main( String[] args ){
  2.  ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
  3.  System.out.println(ctx.getBean("person"));
  4. }

这里,有一个需要注意的地方:通过@Bean的形式是使用的话, bean的默认名称是方法名,若@Bean(value="bean的名称")那么bean的名称是指定的 。

获取Person实例如下所示。

 
 
 
 
  1. public static void main( String[] args ){
  2.  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
  3.  System.out.println(ctx.getBean("person"));
  4. }

@CompentScan注解

我们可以使用@CompentScan注解来进行包扫描,如下所示。

 
 
 
 
  1. @Configuration
  2. @ComponentScan(basePackages = {"com.binghe.spring"})
  3.  public class MainConfig {

excludeFilters 属性

当我们使用@CompentScan注解进行扫描时,可以使用@CompentScan注解的excludeFilters 属性来排除某些类,如下所示。

 
 
 
 
  1. @Configuration
  2. @ComponentScan(basePackages = {"com.binghe.spring"},excludeFilters = {
  3. @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
  4. @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {PersonService.class})
  5. })
  6. public class MainConfig {
  7. }

includeFilters属性

当我们使用@CompentScan注解进行扫描时,可以使用@CompentScan注解的includeFilters属性将某些类包含进来。这里需要注意的是:需要把useDefaultFilters属性设置为false(true表示扫描全部的)

 
 
 
 
  1. @Configuration
  2. @ComponentScan(basePackages = {"com.binghe.spring"},includeFilters = {
  3. @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, PersonService.class})
  4. },useDefaultFilters = false)
  5. public class MainConfig {
  6. }

@ComponentScan.Filter type的类型

  • 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
  • 指定类型的 FilterType.ASSIGNABLE_TYPE @ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,value = {Person.class})
  • aspectj类型的 FilterType.ASPECTJ(不常用)
  • 正则表达式的 FilterType.REGEX(不常用)
  • 自定义的 FilterType.CUSTOM
 
 
 
 
  1. public enum FilterType {
  2.     //注解形式 比如@Controller @Service @Repository @Compent
  3.     ANNOTATION,
  4.     //指定的类型
  5.     ASSIGNABLE_TYPE,
  6.     //aspectJ形式的
  7.     ASPECTJ,
  8.     //正则表达式的
  9.     REGEX,
  10.     //自定义的
  11.     CUSTOM
  12. }

FilterType.CUSTOM 自定义类型

 
 
 
 
  1. public class CustomFilterType implements TypeFilter {
  2. @Override
  3. public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
  4.     //获取当前类的注解源信息
  5.     AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
  6.     //获取当前类的class的源信息
  7.     ClassMetadata classMetadata = metadataReader.getClassMetadata();
  8.     //获取当前类的资源信息
  9.     Resource resource = metadataReader.getResource();
  10.   return classMetadata.getClassName().contains("Service");
  11. }
  12.     
  13. @ComponentScan(basePackages = {"com.binghe.spring"},includeFilters = {
  14. @ComponentScan.Filter(type = FilterType.CUSTOM,value = CustomFilterType.class)
  15. },useDefaultFilters = false)
  16. public class MainConfig {
  17. }

配置Bean的作用域对象

不指定@Scope

在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉加载(容器启动实例就创建好了)

 
 
 
 
  1. @Bean
  2. public Person person() {
  3.  return new Person();

@Scope为 prototype

指定@Scope为 prototype 表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用的时候才会创建)

 
 
 
 
  1. @Bean
  2. @Scope(value = "prototype")
  3. public Person person() {
  4.     return new Person();
  5. }

@Scope取值

  • singleton 单实例的(默认)
  • prototype 多实例的
  • request 同一次请求
  • session 同一个会话级别

懒加载

Bean的懒加载@Lazy(主要针对单实例的bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)

 
 
 
 
  1. @Bean
  2. @Lazy
  3. public Person person() {
  4.  return new Person();
  5. }

@Conditional条件判断

场景,有二个组件CustomAspect 和CustomLog ,我的CustomLog组件是依赖于CustomAspect的组件 应用:自己创建一个CustomCondition的类 实现Condition接口

 
 
 
 
  1. public class CustomCondition implements Condition {
  2. /****
  3. @param context
  4. * @param metadata
  5. * @return
  6. */
  7.     @Override
  8.     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  9.         //判断容器中是否有CustomAspect的组件
  10.         return context.getBeanFactory().containsBean("customAspect");
  11.     } 
  12. public class MainConfig {
  13.     @Bean
  14.     public CustomAspect customAspect() {
  15.         return new CustomAspect();
  16.     } 
  17.     @Bean
  18.     @Conditional(value = CustomCondition.class)
  19.     public CustomLog customLog() {
  20.      return new CustomLog();
  21.     }
  22. }

向IOC 容器添加组件

(1)通过@CompentScan +@Controller @Service @Respository @compent。适用场景: 针对我们自己写的组件可以通过该方式来进行加载到容器中。

(2)通过@Bean的方式来导入组件(适用于导入第三方组件的类)

(3)通过@Import来导入组件 (导入组件的id为全类名路径)

 
 
 
 
  1. @Configuration
  2. @Import(value = {Person.class})
  3. public class MainConfig {
  4. }

通过@Import 的ImportSeletor类实现组件的导入 (导入组件的id为全类名路径)

 
 
 
 
  1. public class CustomImportSelector implements ImportSelector { 
  2.     @Override
  3.     public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  4.      return new String[]{"com.binghe.spring"};
  5.     }
  6. Configuration
  7. @Import(value = {Person.class}
  8. public class MainConfig {
  9. }

通过@Import的 ImportBeanDefinitionRegister导入组件 (可以指定bean的名称)

 
 
 
 
  1. public class DogBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
  2.     @Override
  3.     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  4.         //创建一个bean定义对象
  5.         RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Dog.class);
  6.         //把bean定义对象导入到容器中
  7.         registry.registerBeanDefinition("dog",rootBeanDefinition);
  8.     }
  9. @Configuration
  10. @Import(value = {Person.class, Car.class, CustomImportSelector.class, DogBeanDefinitionRegister.class})
  11. public class MainConfig {
  12. }

通过实现FacotryBean接口来实现注册 组件

 
 
 
 
  1. public class CarFactoryBean implements FactoryBean {
  2.     @Override
  3.     public Car getObject() throws Exception {
  4.      return new Car();
  5.     } 
  6.     @Override
  7.     public Class getObjectType() {
  8.      return Car.class;
  9.     } 
  10.     @Override
  11.     public boolean isSingleton() {
  12.      return true;
  13.     }
  14. }

Bean的初始化与销毁

指定bean的初始化方法和bean的销毁方法

由容器管理Bean的生命周期,我们可以通过自己指定bean的初始化方法和bean的销毁方法

 
 
 
 
  1. @Configuration
  2. public class MainConfig {
  3.     //指定了bean的生命周期的初始化方法和销毁方法.@Bean(initMethod = "init",destroyMethod = "destroy")
  4.     public Car car() {
  5.      return new Car();
  6.     }
  7. }

针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法

针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受IOC容器的管理

通过 InitializingBean和DisposableBean实现

通过 InitializingBean和DisposableBean个接口实现bean的初始化以及销毁方法

 
 
 
 
  1. @Component
  2. public class Person implements InitializingBean,DisposableBean {
  3.     public Person() {
  4.      System.out.println("Person的构造方法");
  5.     } 
  6.     @Override
  7.     public void destroy() throws Exception {
  8.      System.out.println("DisposableBean的destroy()方法 ");
  9.     } 
  10.     @Override
  11.     public void afterPropertiesSet() throws Exception {
  12.      System.out.println("InitializingBean的 afterPropertiesSet方法");
  13.     }
  14. }

通过JSR250规范

通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法

 
 
 
 
  1. @Component
  2. public class Book {
  3.     public Book() {
  4.      System.out.println("book 的构造方法");
  5.     } 
  6.     @PostConstruct
  7.     public void init() {
  8.      System.out.println("book 的PostConstruct标志的方法");
  9.     } 
  10.     @PreDestroy
  11.     public void destory() {
  12.      System.out.println("book 的PreDestory标注的方法");
  13.     }
  14. }

通过BeanPostProcessor实现

通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程

  • postProcessBeforeInitialization 在init方法之前调用
  • postProcessAfterInitialization 在init方法之后调用
 
 
 
 
  1. @Component
  2. public class CustomBeanPostProcessor implements BeanPostProcessor {
  3.     @Override
  4.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  5.      System.out.println("CustomBeanPostProcessor...postProcessBeforeInitialization:"+beanName);
  6.      return bean;
  7.     } 
  8.     @Override
  9.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  10.         System.out.println("CustomBeanPostProcessor...postProcessAfterInitialization:"+beanName);
  11.         return bean;
  12.     }

BeanPostProcessor的执行时机

 
 
 
 
  1. populateBean(beanName, mbd, instanceWrapper)
  2. initializeBean{
  3.     applyBeanPostProcessorsBeforeInitialization()
  4.     invokeInitMethods{
  5.     isInitializingBean.afterPropertiesSet()
  6.     自定义的init方法
  7. }
  8. applyBeanPostProcessorsAfterInitialization()方法
  9. }

通过@Value +@PropertySource来给组件赋值

 
 
 
 
  1. public class Person {
  2.     //通过普通的方式
  3.     @Value("独孤")
  4.     private String firstName;
  5.     //spel方式来赋值
  6.     @Value("#{28-8}")
  7.     private Integer age;
  8.     通过读取外部配置文件的值
  9.     @Value("${person.lastName}")
  10.     private String lastName;
  11. @Configuration
  12. @PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置
  13. public class MainConfig {
  14.     @Bean
  15.     public Person person() {
  16.         return new Person();
  17.     }
  18. }

自动装配

@AutoWired的使用

自动注入

 
 
 
 
  1. @Repository
  2. public class CustomDao {
  3. @Service
  4. public class CustomService {
  5.     @Autowired
  6.     private CustomDao customDao;

结论: (1)自动装配首先时按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照 属性名称来进行装配

 
 
 
 
  1. @Autowired
  2. private CustomDao customDao;

比如,我容器中有二个CustomDao类型的组件 一个叫CustomDao 一个叫CustomDao2那么我们通过@AutoWired 来修饰的属性名称时CustomDao,那么拿就加载容器的CustomDao组件,若属性名称为tulignDao2 那么他就加载的时CustomDao2组件

(2)假设我们需要指定特定的组件来进行装配,我们可以通过使用@Qualifier("CustomDao")来指定装配的组件 或者在配置类上的@Bean加上@Primary注解

 
 
 
 
  1. @Autowired
  2. @Qualifier("CustomDao")
  3. private CustomDao customDao2

(3)假设我们容器中即没有CustomDao 和CustomDao2,那么在装配的时候就会抛出异常

 
 
 
 
  1. No qualifying bean of type 'com.binghhe.spring.dao.CustomDao' available

若我们想不抛异常 ,我们需要指定 required为false的时候可以了

 
 
 
 
  1. @Autowired(required = false)
  2. @Qualifier("customDao")
  3. private CustomDao CustomDao2;

(4)@Resource(JSR250规范) 功能和@AutoWired的功能差不多一样,但是不支持@Primary 和@Qualifier的支持

(5)@InJect(JSR330规范) 需要导入jar包依赖,功能和支持@Primary功能 ,但是没有Require=false的功能

 
 
 
 
  1.     javax.inject
  2.     javax.inject
  3.     1

(6)使用@Autowired 可以标注在方法上

  • 标注在set方法上
 
 
 
 
  1. //@Autowired
  2. public void setCustomLog(CustomLog customLog) {
  3.  this.customLog = customLog;
  4. }
  • 标注在构造方法上
 
 
 
 
  1. @Autowired
  2. public CustomAspect(CustomLog customLog) {
  3.  this.customLog = customLog;
  4. }

标注在配置类上的入参中(可以不写)

 
 
 
 
  1. @Bean
  2. public CustomAspect CustomAspect(@Autowired CustomLog customLog) {
  3.     CustomAspect customAspect = new CustomAspect(customLog);
  4.     return ustomAspect;
  5. }

XXXAwarce接口

我们自己的组件 需要使用spring ioc的底层组件的时候,比如 ApplicationContext等我们可以通过实现XXXAware接口来实现

 
 
 
 
  1. @Component
  2. public class CustomCompent implements ApplicationContextAware,BeanNameAware {
  3.     private ApplicationContext applicationContext;
  4.     @Override
  5.     public void setBeanName(String name) {
  6.      System.out.println("current bean name is :【"+name+"】");
  7.     } 
  8.     @Override
  9.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  10.      this.applicationContext = applicationContext;
  11.     }
  12. }

@Profile注解

通过@Profile注解 来根据环境来激活标识不同的Bean

  • @Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效
  • @Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活
  • 没有标志为@Profile的bean 不管在什么环境都可以被激活
 
 
 
 
  1. @Configuration
  2. @PropertySource(value = {"classpath:ds.properties"})
  3. public class MainConfig implements EmbeddedValueResolverAware {
  4.     @Value("${ds.username}")
  5.     private String userName;
  6.     @Value("${ds.password}")
  7.     private String password;
  8.     private String jdbcUrl;
  9.     private String classDriver;
  10.     @Override
  11.     public void setEmbeddedValueResolver(StringValueResolver resolver) {
  12.         this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}");
  13.         this.classDriver = resolver.resolveStringValue("${ds.classDriver}");
  14.     } 
  15.     @Bean
  16.     @Profile(value = "test")
  17.     public DataSource testDs() {
  18.      return buliderDataSource(new DruidDataSource());
  19.     }
  20.     @Bean
  21.     @Profile(value = "dev")
  22.     public DataSource devDs() {
  23.      return buliderDataSource(new DruidDataSource());
  24.     } 
  25.     @Bean
  26.     @Profile(value = "prod")
  27.     public DataSource prodDs() {
  28.      return buliderDataSource(new DruidDataSource());
  29.     } 
  30.     private DataSource buliderDataSource(DruidDataSource dataSource) {
  31.         dataSource.setUsername(userName);
  32.         dataSource.setPassword(password);
  33.         dataSource.setDriverClassName(classDriver);
  34.         dataSource.setUrl(jdbcUrl);
  35.      return dataSource;
  36.     }
  37. }

激活切换环境的方法

(1)运行时jvm参数来切换

 
 
 
 
  1. -Dspring.profiles.active=test|dev|prod  

(2)通过代码的方式来激活

 
 
 
 
  1. public static void main(String[] args) {
  2.     AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  3.     ctx.getEnvironment().setActiveProfiles("test","dev");
  4.     ctx.register(MainConfig.class);
  5.     ctx.refresh();
  6.     printBeanName(ctx);
  7. }

本文转载自微信公众号「冰河技术」,可以通过以下二维码关注。转载本文请联系冰河技术公众号。

分享题目:IOC容器注解汇总,你想要的都在这儿了!!
文章地址:http://www.shufengxianlan.com/qtweb/news13/539113.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联