Spring之注解开发

news2024/11/16 22:55:24

目录

一:Bean基本注解开发

二:Bean依赖注入注解开发

三:非自定义Bean注解开发

四:Bean配置类的注解开发

五:Spring配置其他注解

六:Spring注解的解析原理


一:Bean基本注解开发

          Spring除了xml配置文件进行配置之外, 还可以使用注解方式进行配置, 注解方式慢慢成为xml配置的替代方案。我 们有了xml开发的经验, 学习注解开发就方便了许多, 注解开发更加快捷方便。 Spring提供的注解有三个版本:

  • 2.0时代, Spring开始出现注解

  • 2.5时代, Spring的Bean配置可以使用注解完成

  • 3.0时代, Spring其他配置也可以使用注解完成, 我们进入全注解时代

 

基本Bean注解, 主要是使用注解的方式替代原有xml的<bean>标签及其标签属性的配置  

<bean  id="" name=""  class=""scope=""   lazy-init="" init-method=""destroy-method=""
abstract=""   autowire="" factory-bean="" factory-method=""></bean>

 

@Component注解

使用@Component注解替代<bean>标签

xml配置注解描述
<bean id=""class="">@Component被该注解标识的类, 会在指定扫描范围内被Spring加载并实例化

案例:

<bean id="userService" class="com.tangyuan.service.UserServiceImpl"></bean>

@Component(value="userService")//value可以省略不写
----需要使用的类-------
public class UserServiceImpl implements UserService{

}
@Component("userDao")
----需要使用的类-------
public class UserDaoImpl implements UserDao{

}

     ps:如果@Component注解中什么内容都不写的话,那就会以类的名称,并且首字母小写作为beanName

@Component注解的源代码
package org.springframework.stereotype;
import...
@Target({ElementType.TYPE} )
@Retention(Retention Policy.RUNTIME)
@Documented
@Indexed
public  @interface Component{
    String    value()   default "";
}

   applicationContext.xml

<!--注解组件扫描:扫描指定的基本包及其子包下的类,识别使用@Component注解-->
<context:component-scan base-package="com.tangyuan"/>

测试:

//创建ApplicationContext,加载配置文件,实例化容器
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Object  aa=applicationContext.getBean("userService");
UserDao  bb=applicationContext.getBean(userDao.class);
  System.out.println(aa);
  System.out.println(bb);

@Scope注解

         @Component就单纯一个value属性, 那么xml配置<bean>时那些属性怎么进行配置呢?Spring是通过注解方式去配置的之前<bean>标签中的那些属性, 例如:@Scope

<bean  id="" name=""  class=""scope=""   lazy-init="" init-method=""destroy-method=""
abstract=""   autowire="" factory-bean="" factory-method=""></bean>

使用@Component注解替代<bean>标签

xml配置注解描述
<bean scope="">@Scope在类上或使用了@Bean标注的方法上, 标注Bean的作用范围, 取值为singleton或prototype
<bean lazy-init="">@Lazy在类上或使用了@Bean标注的方法上, 标注Bean是否延迟加载, 取值为<true和false
<bean init-method="">@PostConstruct在方法上使用, 标注Bean的实例化后执行的方法
<bean destroy-method="">@PreDestroy在方法上使用, 标注Bean的销毁前执行方法
 @Scope注解的源代码
 import...
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interface Scope{
@AliasFor("scopeName")
String value() default"";
    
 @AliasFor("value")
 String scopeName() default "";  
    
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
 }
Lazy注解的源代码
 package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
    boolean value() default true;
}

  • 由于Java EE开发是分层的, 为了每层Bean标识的注解语义化更加明确, @Component又衍生出如下三个注解:

@Component衍生注解描述
@Repository在Dao层类上使用
@Service在Service层类上使用
@Controller在Web层类上使用
@Repository("userDao")
public class UserDaoImpl implements UserDao{}

@Service("userService")
public class UserServiceImpl implements UserService{}

@Controller("userService")
public class UserController{}
@Repository注解
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

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

二:Bean依赖注入注解开发

     Bean依赖注入的注解, 主要是使用注解的方式替代xml的<property>标签完成属性的注入操作

<bean id=" "   class="">
     <property name=""value=""/>
     <property name=""ref="" />
</bean>

Spring主要提供如下注解, 用于在Bean内部进行属性注入的:

属性注入注解描述
@Value使用在字段或方法上,用于注入普通数据
@Autowired使用在字段或方法上, 用于根据类型(byType) 注入引用数据
@Qualifier使用在字段或方法上, 结合@Autowired, 根据名称注入
@Resource使用在字段或方法上,根据类型或名称进行注入
public class UserDaoImpl implements UserDao{
    
    // @Value("李太白")
    @Value("${jdbc.driver}")
    private String username;
    
    //@Autowired //根据类型进行注入,如果同一类型的Bean有多个,尝试根据名字进行二次匹配,匹配不成功再报错
    //expected single matching bean but found 2
    //@Qualifier("userDao2")//种此,结合 @Autowired一起使用,作用根据名称注入相应的Bean
    @Resource(name="userDao2")//不指定名称参数时,根据类型注入,指定名称就根据名称注入
    private UserDao userDao;
    
    @Autowired
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }
    
     @Autowired //根据参数类型进行匹配
    public void xxx(UserDao userDao){
        System.out.println("xxx:"+userDao);
    }
    
      @Autowired //从容器中寻找UserDao类型的Bean,结果保存在对应的集合中
    public void yyy(List<UserDao> userDaoList){
        System.out.println("yyy:"+userDaoList);
    }
}

三:非自定义Bean注解开发

           非自定义Bean不能像自定义Bean一样使用@Component进行管理, 非自定义Bean要通过工厂的方式进行实例化,使用@Bean标注方法即可, @Bean的属性为beanName, 如不指定为当前工厂方法名称

//将方法返回值Bean实例以@Bean注解指定的名称存储到Spring容器中
@Bean("dataSource")//当Bean没有设置值时,会以方法名作为BeanName
public DataSource dataSource() {
DruidDataSource dataSource=new DruidDataSource() ;
dataSource.setDriver ClassName("com.mysql.jdbc.Driver") ;
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis") ;
dataSource.setUsername("root") ;
dataSource.setPassword("1234") ;
return dataSource;
}

//活参数时
public DataSource dataSource(
    @Value("${jdbc.driver}")  String driverClassName,
    //@Autowired UserDao userDao
    @Qualifier("userDao2") UserDao userDao
                            ) {}

PS:工厂方法所在类必须要被Spring管理,要放在一个类里面,并加上@Component注解

如果@Bean工厂方法需要参数的话, 则有如下几种注入方式:

  • 使用@Autowired根据类型自动进行Bean的匹配, @Autowired可以省略

  • 使用@Qualifier根据名称进行Bean的匹配;

  • 使用@Value根据名称进行普通数据类型匹配。

@Bean
@Autowired//根据类型匹配参数
public Object objectDemo01(UserDao userDao) {
      System.out.println(userDao) ;
       return new Object() ;
}

@Bean
public Object objectDemo02(@Qualifier("userDao") UserDao userDao,@Value("S{jdbc.username} ") String username) {
           System.out.println(userDao) ;
           System.out.println(username) ;
            return new Object() ;
}

四:Bean配置类的注解开发

         @Component等注解替代了<bean>标签, 但是像<import>、<context:componentScan>等非<bean>标签怎样去使用注解替代呢?

<!--加载properties文件>
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--组件扫描-->
<context:component-scan base-package="com.tangyuan"/>
<!--引入其他xml文件-->
<import resource="classpath:beans.xml"/>

      定义一个配置类替代原有的xml配置文件, <bean>标签以外的标签, 一般都是在配置类上使用注解完成的

@Configuration //标注当前类是一个配置类(替代配置文件)+@Component
//<context:component-scan base-package="com.tangyuan"/>
//@ComponentScan(basePackages={"com.tangyuan"})//多个
@ComponentScan(com.tangyuan)
//<context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")//多个加上中括号,用逗号隔开
//<import resource="classpath:beans.xml"/>
@Import(XXX.class)
public class SpringConfig{



}

测试:
//xml方式的Spring容器
  ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
  //注解方式加载Spring的核心配置类
    ApplicationContext applicationContext1=new AnnotationConfigApplicationContext( SpringConfig.class);


@Configuration注解的源代码
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

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

    boolean proxyBeanMethods() default true;
}
@ComponentScan注解的源代码
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}
@PropertySource注解的源代码
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.io.support.PropertySourceFactory;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
    String name() default "";

    String[] value();

    boolean ignoreResourceNotFound() default false;

    String encoding() default "";

    Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
@Import注解的源代码
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    Class<?>[] value();
}

            @Configuration注解标识的类为配置类, 替代原有xml配置文件, 该注解第一个作用是标识该类是一个配置类,第 二个作用是具备@Component作用

@Configuration
public class ApplicationContext Config{}

          @ComponentScan组件扫描配置, 替代原有xml文件中的<context:componenit-scan base-package=""/>

@Configuration
@ComponentS can({"com.tangyuan.service", "com.tangyuan.dao"} )
public class ApplicationContext Config{}

base-package的配置方式:

  • 指定一个或多个包名:扫描指定包及其子包下使用注解的类

  • 不配置包名:扫描当前@componentScan注解配置类所在包及其子包下的类

              @PropertySource注解用于加载外部properties资源配置, 替代原有xml中的<context:property- placeholder location=" "/>配置

@Configuration
@ComponentScan
@Property Source({"classpath:jdbc.properties", "classpath:xxx.properties"} )
public class ApplicationContextConfig{}

        @lmport用于加载其他配置类, 替代原有xml中的<import resource="classpath:beans.xml”/>配置

@Configuration
@ComponentScan
@Property Source("classpath:jdbc.properties")
@Import(OtherConfig.class)
public class ApplicationContext Config{}

五:Spring配置其他注解

           扩展:@Primary注解用于标注相同类型的Bean优先被使用权, @Primary是Spring3.0引入的, 与@Component 和@Bean一起使用, 标注该Bean的优先级更高, 则在通过类型获取Bean或通过@Autowired根据类型进行注入时, 会选用优先级更高的

@Repository("userDao")
public class UserDaoImpl implements UserDao{}

@Repository("userDao2")
@Primary
public class UserDaoImpl2 implements UserDao{}
@Bean
public UserDao userDao01() {
     return new UserDaoImpl() ;
 }

@Bean
@Primary
public UserDao userDao02() {
    return new UserDaoImpl2() ;
 }

     扩展:@Profile注解的作用同于xml配置时学习profile属性, 是进行环境切换使用的

<beans profile="test">

               注解@Profile标注在类或方法上, 标注当前产生的Bean从属于哪个环境, 只有激活了当前环境, 被标注的Bean才 能被注册到Spring容器里, 不指定环境的Bean, 任何环境下都能注册到Spring容器里

@Repository("userDao")
@Profile("test")
public class UserDaoImpl implements UserDao{}

@Repository("userDao2")
public class UserDaoImpl2 implements UserDao{}

可以使用以下两种方式指定被激活的环境:

  • 使用命令行动态参数, 虚拟机参数位置加载-Dspring.profiles.active=test

  • 使用代码的方式设置环境变量System.setProperty("spring.profiles.active", "test") ;

六:Spring注解的解析原理

使用@Component等注解配置完毕后, 要配置组件扫描才能使注解生效

  • xml配置组件扫描:

<context:component-scan base-package="com.tangyuan"/>
  • 配置类配置组件扫描:

@Configuration
@ComponentScan("com.tangyuan")
public class AppConfig{ }

          使用xml方式配置组件扫描, 而component-scan是一个context命名空间下的自定义标签, 所以要找到对应的命名 空间处理器NamespaceHandler和解析器, 查看spring-context包下的spring.handlers文件

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNames
paceHandler

查看Context NamespaceHandler类

public void init(){
       this.registerBeanDefinitionParser("component-scan",new
       ComponentScanBeanDefinitionParser() ) ;
}

         将ComponentScanBeanDefinitionParser进行了注册, 对其源码进行跟踪, 最终将标注的@Component的类, 生成对应的BeanDefiition进行了注册

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【区块链】区块链技术学习总结

文章目录一、区块链技术简介1.1 区块链概念1.2 区块链应用1.2.1 区块链1.0技术&#xff1a;比特币1.2.2 区块链2.0技术&#xff1a;以太坊1.2.3 区块链3.0技术&#xff1a;价值互联网二、区块链1.0技术比特币2.1 比特币2.1.1 比特币概念2.1.2 比特币性质2.1.3 比特币解决的问题…

Springboot扩展点之BeanDefinitionRegistryPostProcessor

前言通过这篇文章来大家分享一下&#xff0c;另外一个Springboot的扩展点BeanDefinitionRegistryPostProcessor&#xff0c;一般称这类扩展点为容器级后置处理器&#xff0c;另外一类是Bean级的后置处理器&#xff1b;容器级的后置处理器会在Spring容器初始化后、刷新前这个时间…

第二章 chrony服务器

文章目录第二章 chrony服务器1.1安装与配置1.2同步网络时间服务器1.3 配置时间服务器1.4 chronyc 命令1.5常见时区课后练习第一题&#xff1a;第一台机器从阿里云同步时间&#xff0c;第二台机器从第一台机器同步时间第二题&#xff1a;第一台服务器使用系统时间作为第二台服务…

jetson nano GPIO控制说明

文章目录一.GPIO介绍二.安装GPIO库python库C库三.几种常用的通信协议UARTPWMI2CI2SSPI四.控制函数说明python&#xff08;[参考](https://pypi.org/project/Jetson.GPIO/)&#xff09;C五.例程一.GPIO介绍 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输…

干货 | Web自动化测试中显式等待与隐式等待该怎么用?

在实际工作中等待机制可以保证代码的稳定性&#xff0c;保证代码不会受网速、电脑性能等条件的约束。等待就是当运行代码时&#xff0c;如果页面的渲染速度跟不上代码的运行速度&#xff0c;就需要人为的去限制代码执行的速度。在做 Web 自动化时&#xff0c;一般要等待页面元素…

高压放大器在电子束增材制造聚焦消像散控制技术研究的应用

实验名称&#xff1a;高压放大器在电子束增材制造聚焦消像散控制技术研究的应用 研究方向&#xff1a;增材制造 实验目的&#xff1a; 电子束选区熔化技术&#xff0c;即电子束3D打印技术&#xff0c;属于金属增材制造的分支。该技术以电子束为热源&#xff0c;在计算机控制下以…

华为防火墙配置笔记

防火墙&#xff08;Firewall&#xff09;也称防护墙&#xff0c;是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网&#xff08;US5606668&#xff08;A&#xff09;1993-12-15&#xff09;防火墙是位于内部网和外部网之间的屏障&#xff0c;它按照系统管理员预先定…

实战工作十年的Code Review方法论与实践总结

作为卓越工程文化的一部分&#xff0c;Code Review其实一直在进行中&#xff0c;只是各团队根据自身情况张驰有度&#xff0c;松紧可能也不一&#xff0c;这里简单梳理一下CR的方法和团队实践。 一、为什么要CR 提前发现缺陷 在CodeReview阶段发现的逻辑错误、业务理解偏差、…

CleanMyMac2023Mac下载排行最好的清理工具

CleanMyMac是Mac清理工具&#xff0c;具有很多功能。例如‬&#xff0c;删除大量不可见的缓存文件&#xff0c;可以批量删除未使用的DMG、不完整的下载以及其余的旧包。不过由于MAC系统不像windows那样会产生缓存或系统垃圾&#xff0c; 使用Win电脑很多人会下载各类系统优化软…

MQ面试题总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java面试题…

【流行框架】Zookeeper

&#x1f31f;个人博客&#xff1a;www.hellocode.top&#x1f31f; &#x1f31f;Java知识导航&#xff1a;Java-Navigate&#x1f31f; ⭐想获得更好的阅读体验请前往Java-Navigate &#x1f525;本文专栏&#xff1a;《流行框架》 &#x1f31e;如没有JavaWEB基础&#xff0…

Linux文件目录结构详解

Linux文件目录结构 Linux文件系统是采用级层式的树状目录结构&#xff0c;在此结构中的最上层是根目录“/”&#xff0c;然后在此目录下再创建其他的目录 Linux系统下一切硬件皆文件 具体的目录结构 /bin ->存放最经常使用的指令/sbin ->存放系统管理员使用的系统管理…

从Redis、HTTP协议,看Nett协议设计,我发现了个惊天大秘密

1. 协议的作用 TCP/IP 中消息传输基于流的方式&#xff0c;没有边界 协议的目的就是划定消息的边界&#xff0c;制定通信双方要共同遵守的通信规则 2. Redis 协议 如果我们要向 Redis 服务器发送一条 set name Nyima 的指令&#xff0c;需要遵守如下协议 // 该指令一共有3…

第一章 R语言介绍

1.为何使用R 与起源于贝尔实验室的S语言类似&#xff0c;R也是一种为统计计算和绘图而生的语言和环境&#xff0c;它是一套开源的数据分析解决方案&#xff0c;由一个庞大且活跃的全球性研究型社区维护。但是&#xff0c;市面上也有许多其他流行的统计和制图软件&#xff0c;如…

NLP自然语言处理NLTK常用英文功能汇总

自然语言处理 (NLP) 是一门研究如何让计算机程序理解人类语言的学科。NLTK (Natural Language Toolkit) 是一个 Python 包,可以用于 NLP 的应用开发。 很多数据都是非结构化的,而且包含可以被人类读懂的文本。在用编程方式分析这些数据之前,我们需要对它们进行预处理。在本…

Allegro174版本新功能介绍之背景颜色设置

Allegro174版本新功能介绍之背景颜色设置 Allegro升级到了174的时候,打开的时候默认是黑色的背景,如下图 选择界面 工作界面 和166以及172版本不一样,174支持切换成白色的背景,具体操作如下 选择setup

Java--基础语法

文章目录一、输出hello world二、示例说明三、基本语法三、标识符规则四、注释一、输出hello world public class Helloworld {/*第一个java程序*输出Hello world!!!*/public static void main(String[] args) {//输出Hello world!!!System.out.println("Hello world!!!&…

如何使用Git同时绑定Github以及Gitee

今天接到一项任务&#xff0c;是需要clone一个github上面的项目&#xff0c;正兴高采烈的git clone的时候&#xff0c;git bash框框报错&#xff0c;突然一想&#xff0c;我貌似一直用的Gitee,绑定的也是Gitee,并没有绑定Github,于是就有了这篇博客记录如何使用Git同时绑定Gite…

CTF压轴题解题思路和过程

前言 压轴题难度极大。我在这里详细的记录一下解题思路和过程 题目初探 拿到题目&#xff0c;为三个文件&#xff0c;其中mem_secret-963a4663.vmem为常见内存镜像文件&#xff0c;另外两个文件格式未知。 使用volatility进行分析无法识别profile。 接着分析分析Encryption.…

探索云原生技术之容器编排引擎-Kubernetes/K8S详解(6)

❤️作者简介&#xff1a;2022新星计划第三季云原生与云计算赛道Top5&#x1f3c5;、华为云享专家&#x1f3c5;、云原生领域潜力新星&#x1f3c5; &#x1f49b;博客首页&#xff1a;C站个人主页&#x1f31e; &#x1f497;作者目的&#xff1a;如有错误请指正&#xff0c;将…