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/liangx...

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

http://blog.csdn.net/DL88250/...

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

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

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... http://www.jfox.info/springpr...

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

脚本宝典为你提供优质服务
脚本宝典 » spring入门指南

发表评论

提供最优质的资源集合

立即查看 了解详情