spring总结(三)-高级装配

一、Spring profile
1.1、目的
  • 软件开发过程一般涉及“开发 -> 测试 -> 部署上线”多个阶段,每个阶段的环境的配置参数会有不同,如数据源,文件路径等。为避免每次切换环境时都要进行参数配置等繁琐的操作,可以通过spring的profile功能来进行配置参数的切换。
1.2、方式
  • 项目目录内容,每个环境各有一个包,包中分别包含数据库、日志、路径等配置文件:在这里插入图片描述
  • spring的xml中声明这些bean,实现了通过profile标记不同的环境
<description>spring profile配置</description>

    <!-- 开发环境配置文件 -->
    <beans profile="development">
        <context:property-placeholder
            location="classpath*:common/*.properties, classpath*:development/*.properties" />
    </beans>

    <!-- 测试环境配置文件 -->
    <beans profile="test">
        <context:property-placeholder
            location="classpath*:common/*.properties, classpath*:test/*.properties" />
    </beans>
    
    <!-- 生产环境配置文件 -->
    <beans profile="production">
        <context:property-placeholder
            location="classpath*:common/*.properties, classpath*:production/*.properties" />
    </beans>
  • 通过设置spring.profiles.default和spring.profiles.active这两个属性来激活和使用对应的配置文件。设置的方式如下:

    • 在集成测试类上,使用@Profile注解配置。这个bean只有在production这个配置类是激活状态的时候才会被创建和生效。
    @Bean
    @Profile("production")    
    public DataSource jndiDataSource(){
        JndiObjectFactoryBean jofb=new JndiObjectFactoryBean();
        jofb.setJndiName("jndi/iDS");
        jofb.setResourceRef(true);
        jofb.setProxyInterface(xxx.class);
        return (DataSource) jofb.getObject();
    }
    
    • 作为JNDI条目;
    • 作为环境变量;
    • 作为JVM的系统属性
    -Dspring.profiles.active="production"
    
    • 在web.xml中作为web应用的上下文参数context-param;
    • 在web.xml中作为DispatcherServlet的初始化参数;
    <!-- 在上下文context-param中设置profile.default的默认值 -->
    <context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>development</param-value>
    </context-param>
    
    <!-- 在上下文context-param中设置profile.active的默认值 -->
    <!-- 设置active后default失效,web启动时会加载对应的环境信息 -->
    <context-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>development</param-value>
    </context-param>
    
二、自动装配的歧义和解决方式
2.1、一个接口多个实现类的情况
  • 案例:Dessert接口的三个实现类:Cake、IceCream、Cookies。三个实现类均以@Component注解,那么当注入该Dessert接口的时候,不确定具体使用的是哪个实现类
  • 解决办法有几种:
    • (1)、设置实现类为首选项,在实现类中添加@Primary注解。代表注入的时候优先选择。(隐患是无法保证只有一个首选项)

      @Bean
      @Primary
      public Dessert IceCream(){
      	return new IceCream
      }
      
      <bean id = "iceCream"
      	class = "com.xxx.IceCream"
      	primary = "true" />
      
    • (2)、限定注入接口的实现类的具体名称,利用@Qualifier(“xxx”)注解,参数为具体实现类的beanId。(但是其隐患是,若重构该实现类,修改了其类名,那么beanId也会被修改。那样我们这里写死的注入的beanId名称就会有问题。Qualifier指定的限定符和bean的名称紧耦合,对类名称的任务改动都会导致限定符失效。)

      @Autowrired
      @Qualifier("iceCream")
      public void setDessert(Dessert dessert){
      	this.dessert = dessert
      }
      
    • (3)、在类定义中,通过注解@Qualifier(“coldxx”)为类创建自定义的限定符,使限定符的名称不强依赖类名称。那样在引用注入的时候,可以使用这个自定义的限定符那指定引用的实现类。(其隐患是,如果多个bean存在相同的特性,想到的解决办法是在每个bean上注解多个自定义的限定符,直到可以区分唯一bean,但是java中不允许同一个条目中重复出现相同类型的注解)

      @Bean
      @Qualifier("cold")
      public Dessert IceCream(){
      	return new IceCream
      }
      
      @Autowrired
      @Qualifier("cold")
      public void setDessert(Dessert dessert){
      	this.dessert = dessert
      }
      
      @Bean
      @Qualifier("cold")
      @Qualifier("cold2")//这种是不被允许的
      public Dessert IceCream(){
      	return new IceCream
      }
      
    • (4)、把限定符声明为注解的方式,那么每个限定符的注解名类目是不一样的。

      @Target({ElementType.CONSTRUCTOR,ElementType.fIELD,ElementType.METHOD,ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Qualifier
      public @interface Cold{}
      
      @Target({ElementType.CONSTRUCTOR,ElementType.fIELD,ElementType.METHOD,ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Qualifier
      public @interface Cold2{}
      
      @Bean
      @Cold
      @Cold2
      public Dessert IceCream(){
      	return new IceCream
      }
      
      @Autowrired
      @Cold
      @Cold2
      public void setDessert(Dessert dessert){
      	this.dessert = dessert
      }
      
三、bean的作用域
  • 默认情况下,Spring应用上下文所有bean都是作为单例(singleton)的形式创建的。但是某些类是易变有状态的,这种情况下复用单例的bean是有问题的。
3.1、作用域类型
  • 单例(Singleton):整个应用中,只创建bean一个实例
  • 原型/多例(Propotype):每次的注入或者从Spring应用上下文获取的时候,都会创建一个新的bean。
  • 会话(Session):web应用中,为每个会话创建一个bean实例
  • 请求(Request):web应用中,未每个请求创建一个bean实例
3.2、多例的bean设置
  • 组件扫描和类声明的方式来设置多例

    @Component
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //@Scope("prototype")//两种方式
    public class Notpad(){xxxx}
    
  • java配置中声明Notpad为多例

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //@Scope("prototype")//两种方式
    public Notpad notpad(){
    	return new Notpad();
    }
    
    • xmlz中声明
    <bean id = "iceCream"
    		class = "com.xxx.IceCream"
    		scope = "prototype" />
    
3.3、会话作用域与请求作用域
  • 案例:电子商务应用中,购物车的bean,如果是单例,会导致每个用户拥有相同的购物车;如果是多例,会导致不能两个线程同时使用购物车。会话作用域最合适,因为是与给定用户关联性最大

  • 方式:

    • vaule=session,会告知springWeb应用中的每一个会话创建一个shoppingCart。虽然有多个shoppingCart的实例,但是对于每一个会话来说,这个bean相当于是单例的。在用户进入系统,创建了会话之后,才会创建shoppingCart的实例
    • proxyMode=interface,解决了将会话或请求作用域的bean注入到单例ban中所遇到的问题。当shoppingCart注入到另外单例类的方法中,此时shoppingCart的bean并不存在。此时spring的处理方式是将shoppingCart bean的代理,注入到方法中。当调用改方法的时候,代理会对其进行懒解析并调用委托给会话作用域内真正的shoppingCart bean。interface代表代理要实现shoppingCart接口,并将调用委托给实现bean。
    @Component
    	@Scope(value = WebApplicationContext.SCOPE_SEESION, proxyMode = ScopedProxyMode.INTERFACE )
    public ShoppingCat cart(){xxxx}
    
    	<bean id = "cart"
    			class = "com.xxx.ShoppingCart"
    			scope = "seesion" >
    		<aop:scoped-proxy>
    		//<aop:scoped-proxy proxy-target-class = "false">
    	</bean>
    
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值