spring 基于java的配置

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

7.10 Classpath scanning and managed componets

文档地址: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-classpath-scanning 本章中大部分例子是用xml来指定配置元数据,以生成容器里的每个bean定义.上个部分描述了如何通过资源注解来提供大量的配置元数据.但是,这很多例子中,很多bean定义是在xml文件中完成的,而注解只负责依赖注入.本节描述如何通过扫描路径来检测可选组件.候选组件都是一些能匹配一些条件的类或者在容器中注册了相应的bean定义.这移除了使用xml注册bean的必要,因此你可用使用注解,AspectJ类型表达,又或者你的自定义拦截条件 来选择容器中注册的bean定义.

从spring3.0,spring的java配置项目提供了的很多功能已经是spring核心功能的一部分.这允许你使用java而不是xml文件来定义beans.学习@Configuration,@Bean,@Import,@Dependson注解,并学习如何使用.

7.10.1 @Component and further sterertype annotations

@Repository注解是一个任何能完成repository(也就是DAO)角色或模板的类的标志.使用这些标志可以自动转译异常,如Section 20.2.2,"Exception translation";

spring提供了很多固定注解:@Component,@Service,@Controller,@Repository.@Component是一个spring管理组件的基本模板类型.@Repository,@Service,@Controller是对@Componet的特殊化,应用于特定的场合,例如,他们分别在持久化,服务层,表现层中使用.因此,你可以用@Component来标志你的组件,但你最好用@Repository,@Service,@Controller来替换,因为这样可以使这些类更好的而配合工作操作或者和切面协同.例如,这些模板注解都是切入点的理想目标.spring框架在以后的发布版中@Repository,@Service,@Controller可能会携带额外的语法.因此,当你考虑用@Service或@Component来标注你的服务层是,@Service是更好的选择.同上文所示,@Repository已被当为了一个支持持久层自动异常转译的标志.

7.10.2 Meta-annotations (元注解)

很多spring提供的注解可以作为元注解在你的代码里使用.元注解是指可以在其他注解中使用的注解.例如,上文中提到的@Service注解中就有@Component元注解.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // Spring will see this and treat @Service in the same way as @Component
public @interface Service {/ / ....
}

元注解可以被聚合生成组合注解.例如,spring mvc的@RestController注解就是@Controller和@ResponseBody组合而成的.

另外,组合注解可以重新申明元注解的属性来允许用户自定义.当你只打算暴露一部分元注解属性时这将非常有用.例如,spring的@SessionScope以硬编码的方式控制scope的名字为session,但扔允许自定义proxyMode的值.


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {/*** Alias for {@link Scope#proxyMode}.* <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.*/@AliasFor(annotation = Scope.class)ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;}

@SessionScope不申明proxyMode属性仍可以如下使用


@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {// ...
}

更多细节,请查看spring annotaion programming Model

7.10.3 Automatically detectin classes and registering bean definitions(自动检测类并注册bean定义)

spring 可以自动检测模板类并通过ApplicationContext来注册相应的bean定义.例如,一下两个类将会代理以实现自动检测.


@Service
public class SimpleMovieLister {private MovieFinder movieFinder;@Autowiredpublic SimpleMovieLister(MovieFinder movieFinder) {this.movieFinder = movieFinder;}}@Repository
public class JpaMovieFinder implements MovieFinder {// implementation elided for clarity
}

要自动检测这些类并注册相应的bean,你需要在你的@Configuration类中添加@ComponentScan注解,@ComponentScan中的basePackages属性应该是两个类的共同父包.(另外,你可以制定一个逗号,分号,空白分割的列表来包含每个类的父包);

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {...
}

为了简化,上面的可以直接使用注解你的value属性,如 @ComponentScan("org.example")

以下是相应的xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="org.example"/></beans>
  • context:component-scan的隐式的包含了context:annotation-cofig的功能,所以你在使用context:component-scan时不需要使用context:annotation-config;

  • 类路径包的扫描需要相应的目录实体在类路径中真实存在.当你用Ant构建JARS时,要保证你没有开启你的文件转化jar包任务.另外,在一些环境里,依据安全策略类路径目录将无法暴露.例如,jdk1.7中单独的应用.

还有,当你使用component-scan元素时,AutowiredAnnotaionBeanPostProcessor,CommonAnnotationBeanPostProcessor都是隐式包含的.这意味着这两个组件会自动检测被一起注册,不需要在xml里提供任何bean配置元数据.

另,你也可以不注册AutowiredAnnotaionBeanPostProcessor,CommonAnnotationBeanPostProcessor,这需要你在annotation-config元素中将值设为false;

7.10.4 使用过滤器来自定义扫描

一般而言,用@Component,@Repository,@Service,,@Controller,或其他本身标记了@Component注解的注解才能被检测为可选组件.但是,你可以简单的通过使用自定义过滤器来修改并扩展这个行为.将他们作为includeFilters或excludeFilters的参数添加到@ComponentScan注解里.下面的表将描述拦截选项.

拦截器类型

拦截器类型

annotaion,assignable,aspectj,regex,custom五种. 下面的例子表明所有的@Repository注解都会被排除,并使用以stub结尾的repository替代.

@Configuration
@ComponentScan(basePackages = "org.example",includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),excludeFilters = @Filter(Repository.class))
public class AppConfig {...
}

等同于

<beans><context:component-scan base-package="org.example"><context:include-filter type="regex"expression=".*Stub.*Repository"/><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Repository"/></context:component-scan>
</beans>

@Filter,属性时type,pattern,默认是annotation;你也可以通过设置@ComponentScan的useDefaultFileters=false或设置<component-scan>元素中的use-default-filters="false"来禁用默认过滤器.而受影响的类是标注了@Componnet,@Repository,@Service,@Controller,或者@Configuration的类.

7.10.5 Defining bean medata within components(在components中定义bean的元数据)

spring 的components也可以向容器提供bean定义.你可以像在@Configuration注解类中一样使用@Bean注解来定义bean的元数据.下面是一个简单的例子:

@Component
public class FactoryMethodComponent {@Bean@Qualifier("public")public TestBean publicInstance() {return new TestBean("publicInstance");}public void doWork() {// Component method implementation omitted}}

这个类是一个spring组件类,在它的doWork()方法里有应用特定的代码.然,它也提供了一个bean定义,用一个工厂方法来指向方法publicInstance().@Bean注解标记着工厂方法或其他bean定义属性.例如通过@Qualifier提供的一个qualifier值.其他方法级别的注解可以被@Scope,@Lazy或其他自定义注解等来指定.

  • 可以使用@Lazy同@Autowired,@Inject标志懒加载.在本上下文中,它将注入懒加载代理.

自动装配的字段和方法支持上文已经讨论了,另外讨论的是对@Bean方法自动装配的支持:

@Component
public class FactoryMethodComponent {private static int i;@Bean@Qualifier("public")public TestBean publicInstance() {return new TestBean("publicInstance");}// use of a custom qualifier and autowiring of method parameters@Beanprotected TestBean protectedInstance(@Qualifier("public") TestBean spouse,@Value("#{privateInstance.age}") String country) {TestBean tb = new TestBean("protectedInstance", 1);tb.setSpouse(spouse);tb.setCountry(country);return tb;}@Beanprivate TestBean privateInstance() {return new TestBean("privateInstance", i++);}@Bean@RequestScopepublic TestBean requestScopedInstance() {return new TestBean("requestScopedInstance", 3);}}

上面的例子会自动装配字符串类型的方法参数country的值为一个名为privateInstance的bean的Age属性.一个spring表达式语言元素通过#{<expression>}的形式定义了表达式的值.对于@Value注解,一个表达式解析器会会再解析表达文本之前前查看bean的名称. 在spring的Component里的@Bean方法不同于@Configuration类里的@Bean方法的处理.这个不同在于@Component的类没有通过CGLIB来拦截方法或属性的调用.CGLIB代理是通过在@Configueration类中定义了指向其他协作对象的bean的元数据@Bean方法来调用相应的方法或字段;这些方法并没有通过正常的java语义而是通过容器调用的,为的就是当通过调用@Bean方法来引用其他beans时可以提供正常的生命周期管理和spring的代理.相反的,在一个简单的@Component类里调用@Bean方法的字段或方法会有正常的java语法,而不是一个特殊的CGLIB处理或其他限制条件.

如果你吧一个@bean的方法宣布为static,这可以允许你在bean未实例化之后调用它们.当你定义了后处理器类时,这会非常有意义.因为这些类会再容器生命周期中很早启动,这样会避免在此时触发容器配置的其他部分.

调用@bean的静态方法不会被容器拦截,即使当你在@Configuration类里调用.这主要是技术的限制:CGLIB子类只能重写非静态的方法.结果,直接调用其他的@Bean方法拥有java标准语法,所以工厂方法自身会返回一个独立的实例.

java语言中@Bean方法的存在并不会对spring容器里的bean定义造成直接的影响.你可以自由的在你认为合适的非@Configuration类里申明工厂方法,也可以将之设置为静态方法.但是,在@Configuration类里的常规@Bean方法可能需要重写,所以 他们不能命名为private或final.

@Bean方法可以在一个指定的组件类或配置类里发现,和java 8 发现组件类和配置类中实现接口申明的默认方法一样.这就允许在组装复杂的配置组合时有很大的灵活性.即使通过java8的默认方法使混合继承成为可能.

最后,记住一个单个的class可能对于同一个bean持有多个混合的@Bean方法,混合工厂方法的安排取决于运行时那些依赖是可获得.这个算法同其他配置场景里选择最贪婪的工厂方法和构造器一样:可适依赖数量最多的种类在构造期间获取,同容器如何选择混合@Autowired构造器一样.

7.10.6 命名自动检测组件 Naming autodected components

当一个组件作为扫描过程的一部分进行自动检测时,它的bean的名称是通过BeanNameGenerator策略来告知扫描器的.默认的,spring任何固定类型注解(@Componnet,@Repository,@Service,@Controller)包含一个那么值,并将它提供给对于的bean定义.

如果一个注解没有包含value值或其他可检测的组件(可以被自定义拦截器拦截的bean).默认的bean名称生成器返回一个小写字母开头的非限制的类名称.例如,如果以下两个组件被检测,那么它们的名称应该是myMovieListener或movieFinderImpl;

@Service("myMovieLister")
public class SimpleMovieLister {// ...
}@Repository
public class MovieFinderImpl implements MovieFinder {// ...
}

如果你不想依赖默认的bean命名策略,你可以提供一个自定义命名策略.首先,实现BeanNameGenerator接口,并确保它有一个无参构造器.另外,在配置扫描器时提供一个全匹配符的类名称.

@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {...
}

或者

<beans><context:component-scan base-package="org.example"name-generator="org.example.MyNameGenerator" />
</beans>

首先,思考指定注解的值,因为其他组件可能会引用它.另一方面,当容器进行注入时,名称自动生成策略总是差强人意的.

7.10.7 Providing a scope for autodetected components(为自动检测组件提供作用域)

一般而言,spring管理的组件默认和通用的自动检测组件的作用域一般是单例.但是,有时你需要使用@Scope来定义其他的作用域.使用注解提供作用域的名称来实现.

@Scope("prototype")
@Repostitory
public class MovieFinderImpl implements MovieFinder{
}

web特定的作用域细节,可查看7.4.5章,Request,session,global session,application,and WebSocket scopes

如果你想使用自定义作用域策略而不是使用基于注解方法,你需要实现ScopeMetadataResolver接口,并保证该实现类有一个无参构造器.另外,在配置扫描器时提供一个类的全路径名称.

@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {...
}

xml配置方法

<beans><context:component-scan base-package="org.example"scope-resolver="org.example.MyScopeResolver" />
</beans>

当你使用特定非单例作用域,它可能需要为作用域里的对象提供代理. 这个原因在"scoped beans as dependencies"一节里已经描述.为实现这个目标,component-scan元素提供了一个scoped-proxy元素,它有三个值:no,interfacce,targerClass.例如,下面的配置将会是标准的JDK动态代理:

@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {...
}<beans><context:component-scan base-package="org.example"scoped-proxy="interfaces" />
</beans>

7.10.8 通过注解提供匹配符元数据

我们在7.9.4这节里考虑过,'Fine-tuning annotation-based autowiring with qualifier'. 本节的例子说明在你要解决自动注入条件问题时,你可以使用@Qualifier注解或自定义注解来获得更好的控制.因为这些例子都是基于xml的bean定义,这个通配符元数据通过是通过候选的bean定义使用xml里bean元素的qualifier或meta子元素来定义.当你使用类路径扫描或组件自动检测,你需要提供在候选类里通过类级别的注解来提供匹配符元数据.以下三个例子说明了这个技术:


@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {// ...
}@Component
@Genre("Action")
public class ActionMovieCatalog implements MovieCatalog {// ...
}@Component
@Offline
public class CachingMovieCatalog implements MovieCatalog {// ...
}

作为大部分基于xml的可替换项,要记住注解元数据是基于类定义自身的,而使用xml可以为同一类型的不同bean定义提供它们相应的配置元数据.因为注解是类级别的,而xml里的bean则是实例级别的.

转载于:https://my.oschina.net/u/1590027/blog/751623

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

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

相关文章

WPF 实现3D翻转倒计时控件~

WPF开发者QQ群&#xff1a; 340500857由于微信群人数太多入群请添加小编微信号yanjinhuawechat 或 W_Feng_aiQ 邀请入群需备注WPF开发者 PS&#xff1a;有更好的方式欢迎推荐。接着上一篇倒计时控件01—代码如下一、创建 NumberCardControl.xaml代码如下。<UserControl x:Cl…

Android之Android studio基本调试和快捷键

第一种调试方法: 如果APP是单进程,直接debug运行,如下图 第二种调试方法: 第二种就是调试当前已经处于运行状态下的App,这也是我们用的更多的一种调试手段,即 Attach debugger to Android process 。点击运行按钮右侧第三个按钮,弹出 Choose Process 窗口,选择对应的进…

Windows 2008 R2安装DHCP服务器问题及解决方法

错误一&#xff1a;0x80074E6F 指定的服务器已在目录服务中造成此错误的原因是DHCP服务器没有正常卸载&#xff0c;第二次安装就会报如下图错误解决方法1.卸载DHCP服务器2.重启服务器3.打开adsiedit.msc4.如下图展开到 CNNetServices5.删除CNYour ServerName6.重新安装DHCP服务…

免费动态域名解析

DDNS 顾名思义就是动态域名解析&#xff0c;让域名绑定在动态 IP 上&#xff0c;比如拨号上网的 ADSL 用户。国内的 DDNS 服务有花生壳和 3322.org 这种提供商&#xff0c;我一直在用花生壳的免费 DDNS&#xff0c;可是近期情况非常糟糕&#xff0c;我到北京以来&#xff0c;就…

2021 年 CNCF 和开源速度的年终报告

深入了解开发速度最快的项目&#xff0c;可以很好地表明哪些领域正在起飞&#xff0c;哪些平台可能在未来几个月和几年内取得成功。如何评估一个项目的活跃度&#xff0c;通常从这几个方面, commits, contributions, issues 和 pull requests&#xff0c;而使用气泡图是一种很巧…

清华姚班毕业生不配自信?张昆玮在豆瓣征女友,却被网友群嘲......

全世界只有3.14 % 的人关注了爆炸吧知识不要看脸好好说话没想到&#xff0c;清华也有被瞧不起的一天。上周&#xff0c;山西某网友在D瓣上发布了一则征友贴&#xff1a;总结下来&#xff0c;就是一句话&#xff1a;俺&#xff0c;一介俗人&#xff0c;二本教师&#xff0c;兼职…

python自带的函数有哪些_为什么说 Python 内置函数并不是万能的?

在Python猫的上一篇文章中&#xff0c;我们对比了两种创建列表的方法&#xff0c;即字面量用法 [] 与内置类型用法 list()&#xff0c;进而分析出它们在运行速度上的差异。在分析为什么 list() 会更慢的时候&#xff0c;文中说到它需要经过名称查找与函数调用两个步骤&#xff…

抽象类与接口比较

为什么80%的码农都做不了架构师&#xff1f;>>> 老生重谈&#xff0c;每次谈却有不同的收获。抽象类与接口联系 1、是什么 抽象类&#xff1a; public abstract class Door{public int height 250;public int width 150;void open(){System.out.print(&qu…

Prism源代码解析(IRegionManager)

概要本文主要介绍Prism的IRegionManager, 主要分析源代码的执行流程, 来介绍内部实现的几个核心接口调用过程。通过本文, 你可以熟练的掌握Prism当中以下接口的作用以及使用方法, 如下所示:IRgionManagerINavigationAwareINavigateAsyncIRegionNavigationServiceIConfirmNaviga…

Android后台强制结束进程,Application入口或者activity回调的是哪个方法?

问题描述dengdeng 解决方案1如果是系统强制结束&#xff0c;不会调用的 转载于:https://www.cnblogs.com/yiguobei99/p/4002126.html

日本的电视节目到底能有多特别?

1 是不是设计师忘了开扇窗&#xff1f;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 路灯&#xff1a;&#xff1f;&#xff1f;&#xff1f;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 当代大学生的真实水平&#xff08;素材来源网络&#xff0…

记一次 Oracle无法连接 问题分析

前言今天&#xff0c;同事告诉我&#xff0c;有台Oracle服务器异常断电&#xff0c;重启后发现无法连接了。分析过程1.检查服务状态查看Oracle的listerner服务和service服务&#xff0c;发现都是正在运行状态&#xff0c;说明服务是正常的。2.检查端口状态在客户机上使用&#…

最详细的最小堆构建、插入、删除的过程图解

转载&#xff1a;http://blog.csdn.net/hrn1216/article/details/51465270 1.简介 最小堆是一棵完全二叉树&#xff0c;非叶子结点的值不大于左孩子和右孩子的值。本文以图解的方式&#xff0c;说明 最小堆的构建、插入、删除的过程。搞懂最小堆的相应知识后&#xff0c;最大堆…

初探mysql数据库模式(一)

数据库模式是什么&#xff1f; 数据库模式是描述整个数据库的数据结构和数据库底层架构的事务。它分为逻辑模式&#xff08;俗称&#xff1a;“模式”&#xff09;&#xff0c;外模式(俗称&#xff1a;“子模式”or“用户模式”)&#xff0c;内模式(俗称&#xff1a;“存…

数学界最恐怖的存在!54张图读懂2600年数学史,看完跪下了......

全世界只有3.14 % 的人关注了爆炸吧知识“中国现代数学之父”华罗庚曾说过宇宙之大&#xff0c;粒子之微火箭之速&#xff0c;化工之巧地球之变&#xff0c;生物之谜日用之繁&#xff0c;无处不用数学回首往昔数学始终伴随我们左右纵横交错的几何、繁琐复杂的运算难以求解的方程…

R中大数据量数据框的合并慎重使用rbind

最近在用R处理百万级的数据&#xff0c;程序本身是线性扫描&#xff0c;可是随着数据量的增加&#xff0c;运行时间却不是线性增加&#xff0c;一度几天都运行不完。 怀疑是其中rbind函数造成的&#xff0c;查询到这篇文章&#xff0c;也说了这个问题 http://blog.sina.com.cn/…

python顺序结构实验设计_Python程序设计实验报告二:顺序结构程序设计

安徽工程大学 Python程序设计实验报告 班级 物流192 姓名 周立 学号 3190505227成绩 日期 3月4日 指导老师修宇 实验二 顺序结构程序设计&#xff08;验证性实验&#xff09; 【实验目的】 &#xff08;1&#xff09;掌握数据的输入输出的方法&#xff1b; &#xff08;2&#…

寒窗苦读十多年,我的毕业论文只研究了一个「屁」

全世界只有3.14 % 的人关注了爆炸吧知识放屁&#xff0c;是公共场合里的社交忌讳。在人头济济的电梯和地铁车厢里&#xff0c;一个呼之欲出的屁&#xff0c;对任何人来说&#xff0c;都是一场心理与生理之间的拉锯战。如果选择放屁&#xff0c;虽然疏通了肠道&#xff0c;但却拉…