Spring基础梳理

基本原理

spring的基础是IOC和DI,其实IOC和DI是对同一件事从不同的方面进行描述的,两者在spring中是同一件事务。

IOC:控制反转,在这里就是指创建bean的主动权发生了转移,原来是由类主动创建bean,现在类不再创建bean,而是由框架去创建类,所以类的创建权限发生了转移。

DI:依赖注入,在这里是指每个类所需的外部实例,都是先向框架发出需求请求,然后由框架去将创建好的bean注入到类中,所以类是依赖于框架的。

AOP:面向切面,就是将一些公共功能分离出来的一种技术。

IOC/DI/AOP在spring中实现的技术基础是java动态代理和反射技术。

spring模块框架图如下所示:

spring版本变化

spring2.0版本

spring2.5版本

spring3.0 3.1 3.2

spring4.0 4.1 4.2 4.3

spring 5.0 最新版本

其中spring3.x 需要jdk5+  / spring4.x需要jdk6+ 

spring3.x相比于spring2.5.x的区别可分为以下几个方面:模块管理更加细致,分出的包更多;增加了一些新特性,对原来的一些功能进行了增强;针对java5的核心API升级。

spring装配

spring提供了三种装配机制:在xml中进行显示配置;在java中进行显示配置;隐式的bean发现机制和自动装配机制。(注解是java提供的一种机制,允许你对类进行标记,然后在运行时动态操作标记的类,注解机制包括三部分,注解声明,被注解的类,操作注解的代码(通过反射获取类上的注解))

工作中三种方式的梳理:

1.在xml中进行bean的声明和配置;

2.使用javaconfig在java类中进行配置,此处需要使用的@Configuration/@ComponentScan/@Import/@ImportResource注解,其中@Configuration注解表明该类是spring配置类,@ComponentScan表示启动组件扫描,@Import表示导入其他的配置类,@ImortResource表示导入其他的配置文件。

3.混合使用xml和javaconfig,就是使用@Component/@Bean/@Name/@Autowired/@Inject注解配置bean类,同时使用xml配置公共属性,并启动组件扫描。@Component表示该类是一个组件,spring将自动创建该组件实例,@Autowired表示注入组件实例,@Name和@Component功能类似,@Inject和@Autowired功能类似,但@Name和@Inject是Java规范中提供的注解。

java依赖注入和spring注解的不同点和相同点可以参考:

http://www.cnblogs.com/liangxiaofeng/p/6390868.html

http://bhdweb.iteye.com/blog/1663907

http://blog.csdn.net/DL88250/article/details/4838803

当spring引入第三方库中的组件时,此时就不能使用@Component和@Autowired注解了,若使用JavaConfig引入第三方框架时,@Bean注解将会使用到,它一般用在一个方法上,表示方法返回的实例将作为spring中的实例使用,这样就可以在其他类中,像使用spring其他实例那样直接@Autowired即可。

@Autowired和@Resoure的异同点:http://bhdweb.iteye.com/blog/1663907

spring中的profile

在程序开发中,往往有几个好几环境比如:开发环境、测试环境、生产环境,每个环境的数据库配置等信息都不相同,如果每次都通过修改程序和配置文件来切换开发环境,非常容易出现错误,spring的profile就是为了解决不同环境之间切换问题的。

profile在spring3.1中就出现了,不过spring3.1中@Profile只能应用在类上,而在spring3.2中@Profile已经可以在方法上使用。使用如下所示:

@Configuration                                                                                                                         public class DataSourceConfig{                                                                                                              @Bean                                                                                                                                          @Profile("dev")                                                                                                                              public DataSource embeddedDataSource(){}

        @Bean                                                                                                                                          @Profile("prod")                                                                                                                              public DataSource jndiDataSource(){}

}

上面的类中定义了两个profile,但是只有当规定的profile被激活时,相应的bean才会生成。spring在确定激活profile时,需要依赖两个独立的属性,spring.profiles.active和spring.profiles.default。spring的处理机制是,先查找active确定激活的profile,若没有设置active属性,再去查找default。有多种方式设置两个属性:

作为DispatcherServerlet的初始化属性;                                                                                       作为web应用的上下文参数;                                                                                                         作为JNDI条目                                                                                                                                 作为环境变量(需要用到ServletContextListener,重写contextInitialized方法)                              作为jvm的系统属性                                                                                                                       在测试类上,使用@ActiveProfiles注解设置。 

激活示例和xml配置示例可以参考:http://www.cnblogs.com/yw0219/p/5990056.html  http://www.jfox.info/springprofile%E6%BF%80%E6%B4%BB%E5%A4%84%E7%90%86.html

Spring中Bean的特殊用法

条件化的bean

条件化bean指,只有当满足一定条件时才会创建bean,但是在spring4之前,很难实现这一点,但是spring4引入了一个新的@Conditional注解,它可以用到带有@Bean的注解方法上,如果给定的条件计算结果为true,就会创建bean,否则的话,这个bean会被忽略。spring4重构了@Profile,@Profile使用@Conditional注解实现,代码如下所示:

@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD})                                       @Documented                                                                       @Conditional(ProfileCondition.class)                                                                                    public @interface Profile{    String[] value(); }    

 class ProfileCondition implements Condition{                                                                          public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata){    if(context.getEnvironment()!=null){    MultiValueMapattrs=metadata.getAllAnnotationAttributes(Profile.class.getName()); if(attrs!=null){                                                                                                                       for(Object value:attrs.get("value")){    if(context.getEnvironment().acceptsProfiles((String[])value)){                                                return true;                                                                                                                                       }                                                                                                                                                     }                                                                                                                                            return false;}}return true;}}

自动装配的歧义性处理

当发生歧义性时,spring提供了多种可供选择的方案来解决该问题。

1.标示首选的bean:当spring遇到歧义性时,spring将会使用首选的bean,而不是其他可选的bean.示例如下所示:

@Component                                                                                                                    @Primary                                                                                                                                public class IceCream implements Dessert{...}

2.限定自动装配的bean:spring提供了@Qualifier限定符用于缩小可选的bean。@Qualifier可以和@Autowired与@Inject协同使用。如下所示:

@Autowired                                                                                                                    @Qualifier("iceCream")                                                                                                                   public class setDessert( Dessert dessert){...}

@Qualifier注解所设置的参数就是想要注入的bean的ID,所有使用@Component注解声明的类都会创建为bean,并且bean的ID为首字目小写的类。

也可以创建自定义的限定符如下所示:

@Component                                                                                                                    @Qualifier("cold")                                                                                                                            public class IceCream implements Dessert{...}

此时IceCreate的bean ID的为:cold.

3.自定义限定符注解

java不允许在同一个条目上重复出现相同类型的多个注解,但是java8注解允许出现重复的注解,只要这个注解本身的定义的时候带有@Repeatable注解就可以,不过@Qualifier注解并没有在定义时添加@Repeatable。@Qualifier可以允许我们定义自己的限定符注解,举例如下所示:

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

下面我们就可以使用@Cold注解代替@Qualifierz("cold")

bean的作用域

spring定义了多种作用域,可以基于这些作用域创建bean.

单例:在整个应用中,只创建bean的一个实例。                                                                       原型:每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean的实例。       会话:在web应用中为每个会话创建一个bean实例。                                                                 请求:在web应用中,为每个请求创建一个bean实例。

单例是默认的作用域,如果想修改bean的作用域可是使用@Scope注解,示例如下所示:

 @Component                                                                                                                  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)                                                          public class Cold{.... }

@Scope还有一个proxyMode属性,该属性是解决了将一个会话或请求作用域的bean注入到单例bean中。举例如下所示:

@Component                                                                                                                  @Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES)                                                                   public class ShoppingCart  implements Cart{.... }

@Component                                                                                                                        public class StoreService{                                                                                                                       @Autowired                                                                                                                                    Cart cart;                                    

 }

因为StoreService是单例模式,而ShoppingCart是会话作用域,在spring创建StoreService时,ShoppingCart并不存在,因此通过设置proxyMode属性,spring不会将实际的ShoppingCart注入StoreService中,spring会注入一个代理,只有当StoreService调用cart时,代理会对其进行懒解析并将调用委托给真正的ShoppingCart

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容