当前位置: 首页 > news >正文

深入浅出Spring注解(22)

参考链接

@Scope:指定bean的作用域

源码如下

@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;
}

修饰范围:类型和方法。AliasFor将value和scopeName互为别名默认空字符串。

public enum ScopedProxyMode {
	DEFAULT,
	NO,
	INTERFACES,
	TARGET_CLASS
}

字面意思代理模式范围,用到的时候在说明。

案例1:和@Compontent一起使用在类上

@Component
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)//@1
public class ServiceA {
}

案例2:和@Bean一起标注在方法上

@Configurable
public class MainConfig2 {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public ServiceA serviceA() {
        return new ServiceA();
    }
}

可选值

在这里插入图片描述

    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Scope(WebApplicationContext.SCOPE_APPLICATION)
    @Scope(WebApplicationContext.SCOPE_SESSION)
    @Scope(WebApplicationContext.SCOPE_REQUEST)

Defaults to an empty string (“”) which implies SCOPE_SINGLETON. 默认情况下是单例模式。

如何扩展自定义,实现 Scope接口

public interface Scope {

	Object get(String name, ObjectFactory<?> objectFactory);
	
	@Nullable
	Object remove(String name);
	
	void registerDestructionCallback(String name, Runnable callback);
	
	@Nullable
	Object resolveContextualObject(String key);
	
	@Nullable
	String getConversationId();
}

@DependsOn:指定当前bean依赖的bean

回顾在 xml阶段的使用

    <bean id="bean9" class="com.example.lurenjia.spring.c9.NormalBean$Bean3" depends-on="bean7,bean8"/>
    <bean id="bean8" class="com.example.lurenjia.spring.c9.NormalBean$Bean2"/>
    <bean id="bean7" class="com.example.lurenjia.spring.c9.NormalBean$Bean1"/>

bean9依赖7和8,所以9的创建过程会在7和8之后。

源码

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

	String[] value() default {};

}

修饰范围:类型和方法。value数组指定bean的名称。

案例1:和@Compontent一起使用在类上

@Component
public class Service1 {
    public Service1() {
        System.out.println("create Service1");
    }
}
@Component
public class Service2 {
    public Service2() {
        System.out.println("create Service2");
    }
}
@Component
public class Service3 {
    public Service3() {
        System.out.println("create Service3");
    }
}
@ComponentScan
public class Client {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Client.class);
        System.out.println(context.getBean(Service1.class));
    }
}
create Service1
create Service2
create Service3

默认情况下按照从上到下的顺序加载,这个我们如果想要1加载之前先完成2和3的加载就可以使用这个注解。
在 Service1上添加

@DependsOn({"service2", "service3"})

输出

create Service2
create Service3
create Service1

运行后就会变为231的顺序,保证1加载的时候2和3已经完成加载。

案例2:和@Bean一起标注在方法上

@Configurable
public class MainConfig4 {

    @Bean
    @DependsOn({"service2", "service3"})
    public Service1 service1() {
        return new Service1();
    }

    @Bean
    public Service2 service2() {
        return new Service2();
    }

    @Bean
    public Service3 service3() {
        return new Service3();
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig4.class);
        System.out.println(context.getBean(Service1.class));
    }

}

输出

create Service2
create Service3
create Service1

结果是按照231的顺序加载。

猜想:案例2我想获得的321的顺序应该怎么做?

首先尝试修改bean定义的顺序看看是否有用?

    @Bean
    public Service3 service3() {
        return new Service3();
    }

    @Bean
    public Service2 service2() {
        return new Service2();
    }

输出顺序还是231,猜想 @DependsOn({“service2”, “service3”}) 先定义了2后定义了3。
验证猜想:修改 @DependsOn({“service3”, “service2”}) 输出顺序变为了 321。
得出结论: @DependsOn({“service3”, “service2”}) 中规定了加载的顺序,前面的要先于后面加载。

@ImportResource:配置类中导入bean定义的配置文件

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

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

	Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
}

修饰范围:类型。value和locations通过AliasFor作用互为别名。

案例1 从beans.xml中导入bean

public class ServiceA {
}
public class ServiceB {
}
@ImportResource("classpath:beans21*.xml")
public class Client {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Client.class);
        for (String beanName : context.getBeanDefinitionNames()) {
            System.out.println(String.format("%s->%s", beanName, context.getBean(beanName)));
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <bean id="serviceA" class="com.example.lurenjia.spring.c21.importResource.ServiceA">

    </bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <bean id="serviceB" class="com.example.lurenjia.spring.c21.importResource.ServiceB">

    </bean>
</beans>

在这里插入图片描述

serviceA->com.example.lurenjia.spring.c21.importResource.ServiceA@105fece7
serviceB->com.example.lurenjia.spring.c21.importResource.ServiceB@3ec300f1

@Lazy:延迟初始化

回顾xml中使用

    <bean id="lazyInitBean" class="com.example.lurenjia.spring.c12.LazyInitBean" lazy-init="true"/>

只有用到的时候才会进行初始化动作。

源码

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

修饰范围:类型、方法、构造函数、方法参数。 value值默认为true代表开启延迟初始化。

案例1:和@Compontent一起使用

@Component
@Lazy
public class Service1 {
    public Service1() {
        System.out.println("创建Service1");
    }
}
@ComponentScan
public class client {
    public static void main(String[] args) {
        System.out.println("准备启动spring容器");
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(client.class);
        System.out.println("spring容器启动完毕");
        System.out.println(context.getBean(Service1.class));
    }
}
spring容器启动完毕
创建Service1
com.example.lurenjia.spring.c21.lazy.Service1@971d0d8

案例2:和@Configuration一起使用加在配置类上

@Lazy //@1
@Configurable
public class LazyConfig {

    @Bean
    public String name() {
        System.out.println("create bean:name");
        return "路人甲Java";
    }

    @Bean
    public String address() {
        System.out.println("create bean:address");
        return "上海市";
    }

    @Bean
    @Lazy(false) //@2
    public Integer age() {
        System.out.println("create bean:age");
        return 30;
    }
}
@ComponentScan
public class client {
    public static void main(String[] args) {     
        System.out.println("准备启动spring容器");
        AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext(LazyConfig.class);
        System.out.println("spring容器启动完毕");

        for (String beanName : Arrays.asList("name", "age", "address")) {
            System.out.println("----------");
            System.out.println("getBean:" + beanName + ",start");
            System.out.println(String.format("%s->%s", beanName, context2.getBean(beanName)));
            System.out.println("getBean:" + beanName + ",end");
        }
    }
}

相关文章:

  • [C++基础]-初识模板
  • 【黄啊码】MySQL入门—13、悲观锁、乐观锁怎么用?什么是行锁、页锁和表锁?死锁了咋办?
  • 小小博客项目(servlet实战演练)
  • C++学习(6)——模板
  • C++重载运算符
  • 1027推免分享材料 备份
  • JavaScript---常用JS方法(utils.js)额外篇
  • 《CTF特训营》学习笔记——APK逆向基础
  • 一文带你了解怎样快速上手微信小程序开发
  • 基于注意力机制的深度协同推荐模型
  • 【Linux修炼】6.gcc/g++及Makefile【工具篇】
  • 【Linux】基本的指令(三)
  • 算法学习 | 贪心算法~通过局部最优的选择来得到整体最优解
  • 聊聊Spring Cloud Gateway 动态路由及通过Apollo的实现
  • Python爬虫入狱小技巧
  • 网络传输文件的问题
  • 【笔记】你不知道的JS读书笔记——Promise
  • cookie和session
  • CSS盒模型深入
  • ERLANG 网工修炼笔记 ---- UDP
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React系列之 Redux 架构模式
  • SSH 免密登录
  • 那些年我们用过的显示性能指标
  • 前端之React实战:创建跨平台的项目架构
  • 推荐一个React的管理后台框架
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 说说我为什么看好Spring Cloud Alibaba
  • #100天计划# 2013年9月29日
  • #HarmonyOS:Web组件的使用
  • (27)4.8 习题课
  • (十三)Flask之特殊装饰器详解
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .Net MVC + EF搭建学生管理系统
  • .NET 依赖注入和配置系统
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net连接oracle数据库
  • /bin/rm: 参数列表过长"的解决办法
  • ::什么意思
  • @AliasFor注解
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [android] 看博客学习hashCode()和equals()
  • [Asp.net MVC]Bundle合并,压缩js、css文件
  • [bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序
  • [C++] Windows中字符串函数的种类
  • [ChromeApp]指南!让你的谷歌浏览器好用十倍!
  • [Docker]六.Docker自动部署nodejs以及golang项目
  • [Eclipse] 详细设置护眼背景色和字体颜色并导出
  • [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated c
  • [EULAR文摘] 脊柱放射学持续进展是否显著影响关节功能
  • [go] 迭代器模式
  • [HJ56 完全数计算]