关注公众号领取海量架构师资料

环境搭建

注解的方式是通过配置类的方式来注入组件,注解注入要比XML注入的方式简单,注解注入也需要在前者的基础上,添加一个spring-context的包,也是实际开发中常用的方式。

准备所需Jar包

Spring注解之组件注册

Spring提供了许多的注解配置,这样我们就可以通过注解的方式实现组件的注册,下图就是Spring中经常使用到的注解。 

@ComponentScan和@Configurable

原先xml的方式

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    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.xsd">        <context:component-scan base-package="model">context:component-scan>beans>

使用配置类 @Configurable来标注该类为Spring中的配置类,@ComponentScan(“model”)是为该配置类指定要去扫描的参数。

package config;import org.springframework.beans.factory.annotation.Configurable;import org.springframework.context.annotation.ComponentScan;import model.Product;/** * @Configurable: 该注解是标注该类是配置类 * @ComponentScan:配置要扫描的包 * @author GaoYang */@Configurable@ComponentScan("model")public class MainConfig {}

@Component

使用该注解就可以将Java对象@Component注册到Ioc容器中,@Component注解要是给属性赋值要配合@Value注解为属性赋值。

/**    @Componnt可以指定该对象的id,也可以不用指定    默认id为该类的类名首字母小写 */@Component("students")public class Student {    @Value("01")    private int sid;    @Value("侯宁宁")    private String name;    @Value("男")    private String sex;

配置类

/** * @Configurable: 该注解是标注该类是配置类 * @ComponentScan:配置要扫描的包 * @author GaoYang */@Configurable@ComponentScan("model")public class MainConfig {}

使用@Configuration注入

@Component("students")public class Student {    @Value("01")    private int sid;    @Value("侯宁宁")    private String name;    @Value("男")    private String sex;    public Student() {        super();    }    public Student(int sid, String name, String sex) {        super();        this.sid = sid;        this.name = name;        this.sex = sex;    }    public int getSid() {        return sid;    }    public void setSid(int sid) {        this.sid = sid;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    @Override    public String toString() {        return "Student [sid=" + sid + ", name=" + name + ", sex=" + sex + "]";    }}

测试 

@Bean

使用@Bean注解该可以在我们的spring注册类里标注,创建对象的方法,可以通过一个返回值为该对象的方法去创建该对象,并通过构造器为该对象的属性进行赋值。

// 配置类@Configurable@ComponentScan("model")public class MainConfig {    // 默认id为方法名    @Bean    public Product product1() {        return new Product("张三","hashd",1);    }    // 可以指定id    @Bean("product2")    public Product product2() {        return new Product("张三","hashd",1);    }}

Java-Bean对象

public class Product {    private String name;    private String price;    private int num;    public Product() {        super();    }    public Product(String name, String price, int num) {        super();        this.name = name;        this.price = price;        this.num = num;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getPrice() {        return price;    }    public void setPrice(String price) {        this.price = price;    }    public int getNum() {        return num;    }    public void setNum(int num) {        this.num = num;    }    @Override    public String toString() {        return "Product [name=" + name + ", price=" + price + ", num=" + num + "]";    }}

测试

@TypeFilter

@TypeFilter注解 是通过设置条件来过滤一些资源,我们可以过滤一些资源不让它加载到ioc容器中。它的使用要在@ComponentScan这个注解中国去使用,通过excludeFilters参数传值,excludeFilters是一个数组,可以设定多个@TypeFilter。

@TypeFilter语法

@Configurable@ComponentScan(value = "model",excludeFilters = {        // FilterType.ANNOTATION是通过注解的形式进行过滤        @Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),        // FilterType.ASSIGNABLE_TYPE 是通过给定的类型        @Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {Product.class}),        // FilterType.ASPECTJ 根据正则表达式        @Filter(type = FilterType.ASPECTJ,classes = {""}),        // FilterType.CUSTOM 使用自定义规则        @Filter(type = FilterType.CUSTOM,classes = {TypeFilterImp.class})})public class MainConfig {    // @Bean == }

@FilterType.CUSTOM自定义规则

使用自定义规则,我们必须给它创建一个制定规则的类,这个类要去实现TypeFilter这个接口,并实现match这个方法,过滤器就会根据match方法的返回值加载,如果去ture就去过滤不满足条件的,如果为false则不会去加载!

/**     * MetadataReader:读取到的当前正在扫描的信息     * MetadataReaderFactory:可以获取到其他任何类的信息     */    @Override    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {        // 获取当前类注解的信息        AnnotationMetadata mr = metadataReader.getAnnotationMetadata();        // 获取当前正在扫描的类的信息        ClassMetadata classMetadata = metadataReader.getClassMetadata();        // 获取当前类的资源信息        Resource resource =  metadataReader.getResource();        // 获取当前类的名字        String className = classMetadata.getClassName();        System.out.println("----"+className);        // contains包含“er”        if(className.contains("er")) {            return true;        }        return false;    }}

@Scope

Spring创建对象默认是单例的,使用@Scope来描述也就是scope=“singleton”,另外scope还有prototype、request、session、global session作用域。

各作用域的的作用

singleton单例模式,全局有且仅有一个实例。(默认值)prototype原型模式,每次获取Bean的时候会有一个新的实例。request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,配置实例:request、session、global session使用的时候首先要在初始化web的web.xml中做如下配置:如果你使用的是Servlet 2.4及以上的web容器,那么你仅需要在web应用的XML声明文件web.xml中增加下述ContextListener即可: ...            class>org.springframework.web.context.request.RequestContextListener     ...session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个 portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用。

案例演示

singleton

@Configurable@ComponentScan("model")public class MainConfig {   /**    * @Scope    * prototype: 多实例的  @Scope("prototype")    * singleton: 单实例的  @Scope("person")    * request: 一次请求创建一个实例    * session: 同一个session创建一个实例    * @return    */   @Scope("singleton")   @Bean   public Product product() {    System.out.println("该实例已被创建");    return new Product("张三","hashd",1);   }}

测试代码

public class text {    public static void main(String[] args) {        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);        System.out.println("Ioc容器已创建完成!");        Product bean1 = applicationContext.getBean(Product.class);        Product bean2 = applicationContext.getBean(Product.class);        System.out.println(bean1== bean2);    }}

从下图可以看到,bean1 == bean2 

Layz-bean

@Layz赖加载主要是针对的是单例模式下,单例模式下ioc容器初始化时,就将bean对象注入到了容器中,@Layz注解可以让容器创建时不去注册容器,而是等到第一次调用时才去注册bean对象。此时,创建的对象依然是单例模式!

使用语法

// 配置类@Configurable@ComponentScan("model")public class MainConfig {    /**     * 懒加载:     *      针对的是单实例的bean,默认在容器启动的时候创建对象     *      赖加载:容器启动时不创建对象,当第一次被调用时被创建     *      */    @Lazy    @Bean    public Product product() {        System.out.println("该实例已被创建");        return new Product("张三","hashd",1);    }   

测试

@Conditional

@Conditional注解是根据制定条件来进行注册,需要我创建配置条件的配置类,如果条件满足就进行注册,不满足就不去注册。

语法

配置类

@Configurablepublic class MainConfig {    @Conditional({winCondition.class})    @Bean("wind")    public Product wind() {        System.out.println("该实例已被创建");        return new Product("张三","wind",1);}   

条件类必须去实现Condition接口,并添加为实现的方法!

public class winCondition implements Condition{    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) {        Environment environment = context.getEnvironment();        // 获取当前操作系统的名字        String property = environment.getProperty("os.name");        if(property.contains("Windows")) {            return true;        }        return false;    }}

案例

需求根据当前操作系统去注册组件。

// 配置类@Configurable@Import(Hero.class)public class MainConfig {    // Windows系统    @Conditional({winCondition.class})    @Bean("wind")    public Product wind() {        System.out.println("该实例已被创建");        return new Product("张三","wind",1);    }    // Linux系统      @Conditional({linuxCondition.class})    @Bean("linux")    public Product linux() {        return new Product("李四","linux",2);    }}

条件配置类

public class winCondition implements Condition{    // Windows系统,返回true    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) {        Environment environment = context.getEnvironment();        String property = environment.getProperty("os.name");        if(property.contains("Windows")) {            return true;        }        return false;    }}
public class linuxCondition implements Condition{    /**     * ConditionContext: 判断条件能使用上下文环境     * AnnotatedTypeMetadata: 注释信息     */    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        // 是否Linux系统        // 1、能获取到ioc使用的bean工厂        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();        // 2、获取类加载器        ClassLoader clLoader = context.getClassLoader();        // 3、获取当前环境信息          Environment environment = context.getEnvironment();          String property = environment.getProperty("os.name");        // 5、bean注册类          BeanDefinitionRegistry registry = context.getRegistry();          if(property.contains("Linux")) {              return true;          }        return false;}

测试… 

@import

  • @Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中

  • 加入IOC容器的方式有很多种,@Import注解就相对很牛皮了,@Import注解可以用于导入第三方包 ,当然@Bean注解也可以,但是@Import注解快速导入的方式更加便捷

  • @Import注解有三种用法

第一种用法:直接填class数组

直接填对应的class数组,class数组可以有0到多个。对应的import的bean都将加入到spring容器中,这些在容器中bean名称是该类的全类名 ,比如com.yc.类名

@Import({ 类名.class , 类名.class... })public class TestDemo {}

第二种用法:ImportSelector方式【重点】

这种方式的前提就是一个类要实现ImportSelector接口,假如我要用这种方法,目标对象是Myclass这个类,分析具体如下:创建Myclass类并实现ImportSelector接口

public class Myclass implements ImportSelector {//既然是接口肯定要实现这个接口的方法    @Override    public String[] selectImports(AnnotationMetadata annotationMetadata) {        return new String[0];    }}// 分析实现接口的selectImports方法中的:// 1、返回值:就是我们实际上要导入到容器中的组件全类名【重点 】// 2、参数:AnnotationMetadata表示当前被@Import注解给标注的所有注解信息【不是重点】// 需要注意的是selectImports方法可以返回空数组但是不能返回null,否则会报空指针异常!

以上分析完毕之后,具体用法步骤如下:第一步:创建Myclass类并实现ImportSelector接口,这里用于演示就添加一个全类名给其返回值

public class Myclass implements ImportSelector {    @Override    public String[] selectImports(AnnotationMetadata annotationMetadata) {        return new String[]{"com.yc.Test.TestDemo3"};    }}

第二步:编写TestDemo 类,并标注上使用ImportSelector方式的Myclass类

@Import({TestDemo2.class,Myclass.class})public class TestDemo {        @Bean        public AccountDao2 accountDao2(){            return new AccountDao2();        }}

第三步:编写打印容器中的组件测试类

** * 打印容器中的组件测试 */public class AnnotationTestDemo {    public static void main(String[] args) {        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestDemo.class);  //这里的参数代表要做操作的类        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();        for (String name : beanDefinitionNames){            System.out.println(name);        }    }}

第三种用法:ImportBeanDefinitionRegistrar方式

同样是一个接口,类似于第二种ImportSelector用法,相似度80%,只不过这种用法比较自定义化注册,具体如下:

public class Myclass2 implements ImportBeanDefinitionRegistrar {//该实现方法默认为空    @Override    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {    }}// 参数分析:// 第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息// 第二个参数表示用于注册定义一个bean

第二步:编写代码,自定义注册bean

public class Myclass2 implements ImportBeanDefinitionRegistrar {    @Override    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {        //指定bean定义信息(包括bean的类型、作用域...)        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);        //注册一个bean指定bean名字(id)        beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);    }}

第三步:编写TestDemo 类,并标注上使用ImportBeanDefinitionRegistrar方式的Myclass2类

@Import({TestDemo2.class,Myclass.class,Myclass2.class})public class TestDemo {        @Bean        public AccountDao2 accountDao222(){            return new AccountDao2();        }}

@FactoryBean

编写配置类

// 标记这是一个Spring配置类@Configurationpublic class SpringConfiguration {    // 如果没有@Bean注解,则注入到容器中的id就是方法名(也就是myFactoryBean),但是如果显示的给了值,那么注入到容器中的就是factoryBean    @Bean("factoryBean")    public MyFactoryBean myFactoryBean(){        return new MyFactoryBean();    }}

测试类

public class SpringDemo {    @Test    public void springTest01() throws Exception {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);        // 容器中获取的Bean,实际上就是工厂Bean(MyFactoryBean通过getObject()方法返回的对象)        Object factoryBean01 = context.getBean("factoryBean");        System.out.println("实际上注入到容器中的类型是:" + factoryBean01.getClass());        Object factoryBean02 = context.getBean("factoryBean");        System.out.println("注入到容器内的对象是否是单例:" + (factoryBean01 == factoryBean02));        Object factoryBean03 = context.getBean("&factoryBean");        System.out.println("如果想获取到MyFactoryBean的对象,使用&前缀:" + factoryBean03);        // 输出打印Spring中的所有Bean名称        String[] beanDefinitionNames = context.getBeanDefinitionNames();        for (String beanDefinitionName : beanDefinitionNames) {            System.out.println(beanDefinitionName);        }    }}

最后

感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

注解赋值可以是方法_P7笔记,把Spring注解讲的明明白白相关推荐

  1. 注解@JsonIgnore的使用方法效果及其他相关注解应用

    作用:在json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响. 使用方法:一般标记在属性或者方法上,返回的json数据即不包含该属性. 场景模拟: 需要把一个List< ...

  2. java spring框架 注解_史上最全的java spring注解

    史上最全的java spring注解,没有之一 注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好.不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就 ...

  3. @async注解_史上最全的java spring注解

    史上最全的java spring注解,没有之一 注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好.不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就 ...

  4. JAVA_OA管理系统(四)番外篇:使用Spring注解注入属性

    本文介绍了使用Spring注解注入属性的方法.使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Pos ...

  5. Spring注解编程基石(一)

    目录 Java注解 Java原生注解 元注解 Stereotype 注解 组合注解 组合注解实现的基础 @AliasFor 隐式别名 @AliasFor 和 @Inherited 区别 注解解析工具 ...

  6. requestmapping注解作用_Java高级架构师-Spring 注解编程之注解属性别名与覆盖

    欢迎关注头条号:Java小野猫 注解属性方法 在进入了解 Spring 注解属性功能之前,我们先看一个正常 Java 注解. 在注解中,属性方法与其他类/接口方法写法类似,但是存在一些区别. 注解属性 ...

  7. Java及spring 注解(反射原理)

    java注解: Java5.0以后引入了注解的概念 注解只在源码阶段保留(编译时忽略),不会影响程序内部的东西,决定运行级别 是一个标识 定义一个注解就可以在其他类中使用 1.元注解:注解上面的注解 ...

  8. Spring Boot 动态数据源(Spring 注解数据源)

    本文实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基 ...

  9. spring注解工具类AnnotatedElementUtils和AnnotationUtils

    一.前言 spring为开发人员提供了两个搜索注解的工具类,分别是AnnotatedElementUtils和AnnotationUtils.在使用的时候,总是傻傻分不清,什么情况下使用哪一个.于是我 ...

最新文章

  1. django的哲学很耐人回味
  2. python性能测试模块_python模块介绍- multi-mechanize 通用的性能测试工具
  3. SAP最佳业务实践:重复制造(149)-4发料
  4. rust面向对象_面向初学者的Rust操作员综合教程
  5. 阻塞队列之七:DelayQueue延时队列
  6. 【案例】图片无缝轮播效果
  7. [录1953-1-13] 郭沫若, 宋庆龄 Сталина 谈话记录
  8. 用ES6 Generator替代回调函数
  9. Kuma是什么? Kuma1.0 GA 发布了包含70+新特性和改进
  10. 高等数学:对向量及其线性运算和数量积、向量积的见解
  11. Wireshark文档阅读笔记-TCP Flags
  12. 2019测试工程师面试题
  13. 这些成人世界的“黑话”,你能听懂多少?
  14. 什么是大数据公司面临的问题以及如何使用大数据解决
  15. 设计模式篇:状态模式(一)
  16. 亚信科技笔试java
  17. jaybird+x3+android,小米首款运动耳机
  18. 另一个jar包引不了_佛说:失去是另一种拥有(醍醐灌顶,发人深思!)
  19. 高速公路计算机知识,高速公路基本知识120问
  20. 人体呼吸心跳感应雷达模块,智能家居传感技术,存在感应雷达应用

热门文章

  1. MySQL普通用户修改密码
  2. 干掉 if 语句,一个不留的那种!
  3. java.lang.IllegalArgumentException: Can not set XXX to com.sun.proxy.$Proxy28
  4. TPO 按主题刷题记录
  5. Android踩坑日记:Android字体属性及测量(FontMetrics)
  6. python开发的模型部署_使用Python部署机器学习模型的10个实践经验
  7. 双指针算法(三):力扣【167.两数之和 | 经典例题
  8. 在Win7中使用Python的MySQLdb模块
  9. 宇视智能锁门禁服务器,宇视T1P系列智能锁
  10. 键盘鼠标录制哪个好用_好看好用还不贵的那种键盘鼠标真的有吗?这次还真让我碰到了...