记录常用的spring注解

1.@Configuration 和 @Bean

spring中可以使用xml 的方式进行配置, 也可以使用 @ Configuration 来指定一个类为配置类, 并使用 @Bean 来对spring容器进行注入.方法名即是id

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

并使用如下方式获取容器,并获取注入的对象

ApplicationContext applicationContext = new  AnnotationConfigApplicationContext(MainConfig.class); //获取容器

		Person bean = applicationContext.getBean(Person.class);//获取对象

2. @ComponentScan 包扫描注解

​ 在xml中,我们使用 :<context:component-scan base-package="com.test.****"/>来进行包扫描,只要是加了 @Controller,@service ,@Repository,@Component 这四个注解的类,都会自动的被注入到容器中.同样,我们也可以使用 注解的方式进行配置,在@Configuration注解声明的配置类上加上 @ComponentScan 注解:

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

在ComponentScan中还有很多属性,可以进行定义扫描规则:

  1. value : 指定扫描的包路径

  2. excludeFilters :指定扫描的时候按照什么规则排除那些组件 ,接受一个 @Filter 的数组

    例:@Filter(type=FilterType.ANNOTATION,classes={Controller.class}), 按照注解类型的方式进行过滤(还有很多种),过滤@Controller注解的类.

  3. includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件, 使用方法和excludeFilters一样,但是还要将spring的自动扫描规则关闭,才能生效(和xml相似),设置属性 :useDefaultFilters = false

如果需要多种过滤规则时,可以使用@ComponentScans 注解 ,可以接受多个@ComponentScan


下面是@Filter 的type属性的详细配置:

  1. 按照注解排除或注入: type=FilterType.ANNOTATION(常用)

  2. 按照给定的类型 : type=FilterType.ASSIGNABLE_TYPE (常用)

  3. 使用ASPECTJ表达式 : type=FilterType.ASPECTJ(不常用)

  4. 使用正则表达式 : type=FilterType.REGEX(不常用)

  5. 使用自定义的规则(实现TypeFilter) : type=FilterType.CUSTOM(不常用,但很灵活)

    例:

    public class MyTypeFilter implements TypeFilter {
    
    	/**
    * metadataReader:读取到的当前正在扫描的类的信息
    * metadataReaderFactory:可以获取到其他任何类信息的
    */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
    throws IOException {
    // TODO Auto-generated method stub
    //获取当前类注解的信息
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    //获取当前正在扫描的类的类信息
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    //获取当前类资源(类的路径)
    Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName();
    System.out.println("--->"+className);
    if(className.contains("er")){
    return true;
    }
    return false;
    } }

    本例中的过滤规则是类名中带有er的进行注入,按照返回值得true或false来决定是否注入

3.@Scope 域注解

调整注入对象的作用域,可以设置为单实例或多实例,例:

    @Scope
@Bean
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}

Scope注解的具体取值:

  1. prototype, 多实例,IOC容器在启动时不会创建对象,每次获取的时候才会去调用方法创建对象
  2. singleton,单实例,默认的取值,IOC在启动时就会创建对象,每次获取都是同一个对象,直接从容器中拿
  3. request,同一次请求创建一个实例 (不用)
  4. session 同一个session创建一个实例(不用)

在使用单实例加载方式的时候,在IOC容器启动时,就创建对象,如果想要在获取时,在创建,可以使用@Lazy 注解,使Bean懒加载

4. @Conditional 判断Bean是否注入

在某些情况,我们需要根据情况来决定是否注入类,获取注入不同的类,这时我们就需要使用@Conditional 注解

我们需要继承Condition类,例:

//判断是否liunx系统
public class LinuxCondition implements Condition { @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定义的注册类(管理类,可以判断是否注入,创建 ,删除注入的Bean)
BeanDefinitionRegistry registry = context.getRegistry();
//获取操作系统属性
String property = environment.getProperty("os.name"); //可以判断容器中的bean注册情况,也可以给容器中注册bean
//判断容器中是否有person类
boolean definition = registry.containsBeanDefinition("person");
if(property.contains("linux")){
return true;
} return false;
} }

使用:

@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
return new Person("linus", 48);
}

如果系统是liunx 才会注入该Bean ,如果不是,将不会注入, 如果将该类加载配置类上,则表示,只有当条件满足时,才会加载配置类中的Bean

5.@Import注解 快速给容器中导入一个组件

通过注解注入对象的方式,已经有两种,分别是:

  1. @ComponentScan注解进行包扫描,这主要针对自己写的类,只有自己写的类,才可以方便我们家@Controller/@Service/@Repository/@Component 这四个注解
  2. @Bean 向容器中注入一个对象,可以方便我们导入第三方的类

第三种方法,就是使用@Import 注解.例

@Import({Color.class,Red.class)

在配置类上加上该注解代表 向容器中注入Color类和 Red类,默认的id是类的全类名

Import注解除了可以直接指定导入的对象外,还支持更加丰富的注入方式

  1. ImportSelector 的实现类:

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

    返回的数组就是需要注入的Bean的全类名数组

  2. ImportBeanDefinitionRegistrar 的实现类:

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

    在方法内部进行操作,使用BeanDefinitionRegistry 对象进行注入

6.FactoryBean 注册组件

这又是一个向容器中注入对象的方法, 首先先实现 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;
} }

并将该工厂类注册到容器中

	@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}

但是当我们通过id获取时,却是getObject方法返回的对象Color,如果我们想获取到工厂对象的本身,可以在id的前面加'&' 即&colorFactoryBean 即可获取到工厂对象的本身.

7.指定注入对象的创建和销毁方法

在xml中,可以使用 init-method和destroy-method 两个属性,指定Bean的初始化方法和销毁方法,如果使用注解,则可以用@Bean 的属性来指定

@Bean(initMethod="init",destroyMethod="detory")
public Car car(){
return new Car();
}

如上例,就指定初始化方法为init,销毁方法为detoty.

Bean的初始化方法是在Bean创建后,调用方法,进行赋值,Bean的销毁方法,和Bean是否是单实例有关,如果Bean是单实例的,销毁方法会在容器关闭时调用,如果是多例的,在从容器中取出该对象时,容器就不进行管理了,所以在容器关闭时,是不会调用销毁方法的.

另一种方法就是实现两个接口 ,一个是InitializingBean 实现的方法就是初始化方法, DisposableBean 实现的方法就是销毁方法.

还有一种是使用注解标注Bean的方法 . @PostConstruct 在 Bean创建完成并且属性赋值完成,来执行初始化方法@PreDestroy : 在容器销毁Bean之前通知我们进行的清理工作

最后一种方式使用的是 通知的方式 实现BeanPostProcessor 接口 ,并将实现类注入到容器中,就可以实现在任何Bean的任何初始化方法执行前执行postProcessBeforeInitialization方法, 并在任何初始化方法之后执行postProcessAfterInitialization方法.(spring源码中大量使用)

@Component
public class MyBeanPostProcessor implements BeanPostProcessor { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
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;
} }

8.@Value 给属性赋值

使用@Value注解给属性赋值,他的使用方法 和xml文件中 value属性一致,可以直接赋值字符串:@Value("张三"),或者是Spring的表达式:@Value("#{20/2}"), 也可以取出配置文件中的值(环境变量中值):@Value("${name}").

最新文章

  1. [转]MySQL批量更新死锁案例分析
  2. 线性回归&amp;&amp;code
  3. 安装Weblogic12.1.3时遇到jre1.7.0_71不是有效的 JDK
  4. 所有外包项目威客网站列表----来自程序员接私活网qxj.me
  5. 用PowerShell批量收回wsp包
  6. 2014联合三所学校 (HDU 4888 HDU 4891 HDU 4893)
  7. TCP/IP 和HTTP 协议基础知识
  8. UIButton图片文字控件位置自定义(图片居右文字居左、图片居中文字居中、图片居左文字消失等)
  9. Problem B: 时间和日期类(III)
  10. react.js - 基于create-react-app的打包后文件根路径修改
  11. 0418 jQuery笔记(添加事件、each、prop、$(this))
  12. 微软跨平台ORM框架之EFCore — 约定与属性映射
  13. Linux 三剑客(Awk、Sed、Grep)
  14. C#实现按键弹出查询窗口
  15. vue.js+webpack在一个简单实例中的使用过程demo
  16. XXS level9
  17. linux下mysql 5.7.22 安装
  18. 安卓程序代写 网上程序代写[原]vim编辑器配置及常用命令
  19. python记录_day08
  20. hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形

热门文章

  1. 002-Java数据类型
  2. Java面试(2)
  3. ARM GNU 专有符号
  4. GNU 交叉工具链的介绍与使用
  5. linux zip,tar压缩文件夹 忽略 .git 文件夾
  6. [转]SpringMVC框架入门配置 IDEA下搭建Maven项目
  7. java多线程-AbstractQueuedSynchronizer
  8. [JZOJ3235] 数字八
  9. Kmeans算法实现
  10. USART 串口