Spring
Spring简介
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring是一个轻量级的控制反转(IoC)和面向切面的容器框架。
- 轻量:从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖Spring的API,能对各开源框架集成得非常的完美。多简单点就是我们自定义的类一般不会引用Spring包,和Spring的API无关。
- 控制反转:其促进了松耦合。应用了IoC,一个对象依赖的其他对象会通过被动的方式传递进来。各个对象之间的联系,创建,管理都由Spring容器来完成。
- 面向切面:Spring提供了面向切面编程的支持,其允许通过分离应用的业务逻辑与系统级服务和事物进行内聚性的开发。应用对象只实现业务逻辑,不负责系统其他的关注点,如日志或事物支持等,这些可以通过切面编程来实现,实现业务分离。
Spring框架的七个模块
-
核心容器
这是Spring框架最为基础的部分,它提供依赖注入来实现容器对Bean的管理。这里最基本的概念是BeanFactory,他是任何Spring引用的核心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的引用代码分离出来。
-
应用上下文(context)模块
BeanFactory使Spring成为一个容器,而上下文模块使他成为一个框架。context增加了对国际化消息,事物传播以及验证的支持。
-
AOP模块
-
JDBC抽象和DAO模块
使用JDBC常常导致大量代码的重复(取得连接,创建语句,处理结果集,关闭连接)。Spring的JDBC和DAO模块抽取了这些重复的代码,使用数据库访问的代码干净简洁。此外这个模块还在几种数据库服务器给出了错误消息上建立了一个更有意义的异常类,我们不在试图破译神秘的SQL错误消息。
-
对象/关系映射集成模块(ORM)
-
Spring的Web模块
Web上下文模块建立于应用上下文模块之上,提供了一个适合Web应用的上下文。
-
SpringMVC框架
控制反转(IoC)
IoC(Inversion of Control)不是一种技术,而是一种思想(其实现有依赖注入来完成),一个重要的面向对象编程的法则。传统应用程序都由我们在类内主动创建,指定依赖,从而导致类与类之间的高耦合性。
而有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,有容器进行注入组合对象,所以对象和对象之间和松耦合的,使整体结构更易于维护。
简单来说,控制反转就是把原本由程序员创建,管理对象的任务全部交给容器来处理。
依赖注入(DI)
常用的注入方式主要有三种:构造方法注入,Setter注入,基于注解注入。
构造方法注入
保证了一些必要的属性在Bean实例化时就设置,并且确保了Bean实例在实例化后可以使用
构造方法注入,不用在类中为属性设置setter方法。但是必须提供构造方法。
- 通过索引的方式注入
<bean id="hello" class="com.bendy.pojo.Hello">
<constructor-arg index="0" value="hello"/>
<constructor-arg index="1" value="world"/>
</bean>
-
通过属性的类型的注入
<bean id="hello" class="com.bendy.pojo.Hello"> <constructor-arg type="java.lang.String" value="hello"/> </bean>
-
通过属性的名称注入
<bean id="hello" class="com.bendy.pojo.Hello"> <constructor-arg name="name" value="bendy"> <constructor-arg name="pwd" value="1234"/> </bean>
Setter注入
-
根据property标签的name属性的值去找对应的setter方法。
例如:name=“aa” 对应的就是通过setAa方法来设置其值
- 由于属性注入具有可选性和灵活性高的优点,是实际最为常用的注入方式
- 属性注入要求Bean提供一个***默认的构造方法***(如果对象有有参构造也一定需要无参构造),并为需要的注入的属性提供setter方法。Spring先调用bean默认的构造方法实例化bean对象,然后通过调用setter方法注入属性值
Student类:
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String > card;
private Set<String > games;
private String wife;
private Properties info;
/*setter/getter方法*/
}
属性注入:
<bean id="address" class="com.bendy.pojo.Address" scope="prototype">
<property name="address" value="湖北省黄冈市"></property>
</bean>
<bean id="student" class="com.bendy.pojo.Student">
<!-- 第一个,普通值注入,value-->
<property name="name" value="bendy"></property>
<!-- 第二种,Bean注入,ref-->
<property name="address" ref="address"></property>
<!-- 第三种,数组注入-->
<property name="books">
<array>
<value>计算机基础理论</value>
<value>数据库概论</value>
<value>高等数据</value>
<value>概率论</value>
<value></value>
</array>
</property>
<!-- List集合注入-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
</list>
</property>
<!-- Map注入-->
<property name="card">
<map>
<entry key="身份证" value="122343423"/>
<entry key="银行卡" value="121324324"/>
</map>
</property>
<!-- Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!-- 空值null注入-->
<!-- <property name="wife" value=""></property> 空字符串注入-->
<property name="wife">
<null/>
</property>
<!-- Properties-->
<property name="info">
<props>
<prop key="学号">12312312312</prop>
<prop key="性别">男</prop>
<prop key="班级">机科三班</prop>
</props>
</property>
</bean>
注解注入
-
方式一:在xml配置文件中注册各个bean对象,其属性通过注解实现输入。
需要在配置文件中加入对注解的支持:<context:annotation-config/>
例子:
private String name; //这里加入Autowired就可以自动装配了 这里于bean的隐式自动装配一致 属性名cat需要与xml文件中id的值对应 若找不到对应的值 就会报错\ //加入了Autowired注解就不用了写这个属性的set方法了 @Autowired(required=false) //required值为false 表示该属性可以为空 默认是为true 不为空 private Cat cat; @Autowired @Qualifier(value = "dog") //这里显示的指定xml文件中对应的bean private Dog dog;
-
方式二:不用在配置文件中显示的注册bean对象,使用注解就可以实现bean对象的注册,但要在配置文件中加入对注解的支持,以及包扫描器(用于扫描各个bean对象)。
对注解的支持:<context:annotation-config/>
加入包扫描器:<context:component-scan base-package=“com.bendy”/>
@Component @Scope("singleton") //标记该类是单例模式 只有一个实例 public class User { // 相当于<property name="name" value="bendy"/> @Value("bendy") //这可以显示的设置默认值 也就不需要自己注入了 public String name; //这里属性已经有值了就可以不用注入了 既不需要set方法 @Value("Jack") //@Value注解也可以标记set的方法来完成注解 与上面的作用一致 public void setName(String name){ this.name=name; } }
-
方式三:使用配置类。完全使用注解来完成bean对象的注册以及属性的注入。这种方式都不需要xml配置文件。
例子:
@Configuration //用于标记该类是配置类 @Import(MyConfig2.class) //与xml文件中的<import resource=".xml">作用一致 @ComponentScan("com.bendy") //扫描包 与xml文件中<context:component-scan base-package="com.bendy"/>作用一样 public class MyConfig { @Bean //这相当于xml文件中的<bean id="user" class="com.bendy"> public User getUser(){ //使用配置类配置Spring getBean中的参数应该是方法名getUser return new User(); } }
几个常用注解
@Autowired:
一般作用于字段上 加上这个注解的字段就可以完成自动装配 这里需要这个字段与xml文件中bean的id值相对应或者class的值相对应
使用了这个注解的字段也可以不用编写set方法
Autowired还有参数required其值为false时 说明该字段可以为空 默认是不为空的 这里可以为空说明在xml文件中可以不存在对应的bean
@Autowired(required=false)
@Nullbale:
字段标记了这个注解 说明这个字段可以为null 也可以标记在方法中的参数
@Qualifier(value=“”):
若@Autowired注解难以完成自动装配时 就需要该注解 其参数用于指定特定的Bean注入
@Resource(name="") :
这是Java的注解 与@Autowired类似 但是比它更加高级 先通过byName 然后再通过byType 这里需要xml文件中对应的bean的id是唯一的
其参数name默认为空 name可以指定特定的bean 与@Autowired参数的required用法一致
@Resource和@Autowired的区别:
都是用来自动装配,都可以放在属性字段上
@Autowired通过byType的方式实现 如果Type唯一则注入 不唯一在通过byName方式
@Resource 默认是通过byName的方式实现的,如果找不到对应的名字则通过byType的方式实现
面向切面AOP
简介
如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用。
AOP即Aspect Oriented Program面向切面编程。