spring教程
springIOC
#控制反转
#创建对象和管理对象的关系,降低他们的耦合度
#是其他功能的基础
#spring容器是IOC的核心
springAOP
面向切面编程,可以处理一切对象的共同业务,降低共同业务和对象之间的耦合度
spring MVC
自动实现mvc给代码分层,进一步降低servlet和jsp内部的耦合度
spring整和
管理jdbc,提高开发效率,整合mybatis,hibernate,structs2,降低技术中对象的耦合度
1.spring容器
1.1 BeanFactory和ApplicationContext是容器的两个接口,后者继承前者,常用后者
ApplicationContext a=new ClassPathXmlApplicationContext(str)
实例化容器后从ClassPath路径下读取配置文件,bean类交给spring容器创建。
创建是通过反射和代理类调用实现的。
1.2 Spring容器新建Bean对象.
先实例化容器,在配置文件中添加beean标签,bean取名用id或者name。
<bean id="arraylist" class="java.util.ArrayList"></bean>
再从容器中获取指定id的bean List list = (ArrayList)a.getBean(“arraylist”)
或者 List list = a.getBean(“arraylist”,ArrayList.class)
在配置文件中创建Bean标签
##-静态工厂方法实例化(了解)
一些类构造方法是私有的,只能通过类的静态方法创建对象,method是要调用的方法。使用 construtor-arg 元素为工厂方法传递方法参数
<bean id="calendar" class="java.util.Calendar" factory-method="getInstance">
<constrcutor-arg index=0 value="dsfds"></constuctor>
</bean>
##-实例工厂方法实例化(了解),必须引用在容器中声明过的对象。
非静态方法的创建对象
<bean factory-bean="calendar" factory-method="getTime" id="obj3"></bean> factory-bean是要调用对象的名称id,
1.3 Bean的作用域:spring默认的singlon只创建一个类的一个实例,可以更改bean的作用域。Bean标签中添加scope=”prototype”,表示一个容器实例化多个实例。request表示对象的声明周期和request相同,session原理相同
1.4 Bean的生命周期
Spring管理bean 的生命周期,让spring自动调用该bean的初始化和销毁方法。在bean的标签中添加<bean id="demo" class="bean.BeanDemo" init-method="init" destroy-method="destroy"></bean>在容器创建之后自动调用init方法,容器关闭时自动调用destroy销毁。
销毁方法只适合单例模式,如果想要关闭容器.
在顶级bean也可以添加default-init-method和destroy方法,(了解)
1.5 bean延迟实例化
如果想bean在获取时初始化,可以在bean标签中添加lazy-init=“true”,只对单例的bean有效。
2 spring IOC 控制反转
2.1 对象的依赖关系由容器处理,容器采用DI方式是实现IOC
2.2 DI: 依赖注入,有两种方式setter注入和构造器注入实现。(8大基本数据类型注入和引用类型注入)
##setter注入: 通过bean类(有无参构造器)的set方法注入,在配置文件中的增添property标签
<bean id="" class="">
<property name="" value=""/>
</bean>
##注入的是基本数据类型、String、基本封装类型,value里写字符串,spring能自动转型进行参数注入
##bean注入的是另一个bean,把value替换成ref,<property name="computure" ref="computer"/> ref的值是另一个bean的id,或者用ref标签<ref bean=""/>全局查找 <ref local=""/>当前文件查找bean,都是用来引用bean
## p命令空间注入 需要引入<xml:p=h"http://www.springframework.org/schema/p"> <bean id="message" class="bean.MessageTest" p:name="zhouyang" //直接值, p:dao-ref="beanId" 表示dao是一个引用对象> 用于set注入
## c命令空间注入 需要引入<xml: c="http://www.springframework.org/schema/c"/> <bean id="message" class="bean.MessageTest" c:name="zhouyang" c:dao-ref="beanId"> 用于构造器注入
补充:在xml配置文件中可以读取properties配置文件,
方法一:<util:properties id=”p”location=”classPath:xx.properties”/>,后面使用spring表达式#{}使用
方法二:spring2.0中,声明一个bean,读取properties,在后面使用${key}读取属性值
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classPath:x.properties</value>
</property>
</bean>
方式三:spring2.5中,<context:property-placeholer location="classpath:xx.xml"/> 读取${key}
##构造器注入 在bean的类中有参数的构造器(bean类可以有无参构造器,写上是个好习惯),bean的参数必须传入,往往是为了强制 注入参数。
<bean id="mobile" class="bean.MobileCellphone">
//根据index注入
<constructor-arg index="0" value="ARM"/> //注入基本类型,用value
<constructor-arg index="1" ref="listMessage/> //注入其他bean
//根据类型注入
<constructor-arg type="java.lang.String" value="zhouyang">
##bean引用补充
补充:对于ref引用的bean,也可以这样声明成内部bean,set注入或者构造器注入都可以
<bean id="CustomerBean" class="com.yiibai.common.Customer">
<property name="person">
<bean class="com.yiibai.common.Person">
<property name="name" value="yiibai" />
<property name="address" value="address1" />
<property name="age" value="28" />
</bean>
</property>
<constructor-arg>
<bean class="com.yiibai.common.Person">
<property name="name" value="yiibai" />
<property name="address" value="address1" />
<property name="age" val‘’ue="28" />
</bean>
</constructor-arg>
</bean>
##注入集合:给list(数组) set map properties集合注入参数(简单值或者引用表示集合)
<property name="list">
<list>
<value>北京</value>
<value>上海</value>
<value>天津</value>
<ref bean="address1"/>
</list>
</property>
<property name="set">
<set>
<value></value>
<value>张三</value>
<ref bean="address2"/>
</set>
</property>
<property name="map">
<map>
<entry key="jsd1604" value="80"/>
<entry key="jsd1605" value="90"/>
<entry key ="two" value-ref="address1"/>
</map>
</property>
<property name="properties">
<props>
<prop key="user">openman</prop>
<prop key="pwd">123456</prop>
</props>
</property>
##引用的方式注入集合,先申明一个util标签,在bean中引用它.
<util:list id="listMessage">
<value>张三</value>
<value>李四</value>
</util:list>
<bean id="message" class="bean.MessageTest">
<property name="list" ref="listMessage"/>
</bean>
2.3 xml配置文件可以继承bean,在子bean中属性指定parent="id"指定父bean,这样子bean就可以继承父bean的配置,如果不想实例化父bean,只当做模板,那么在父bean的属性指定abstract=“true”,也可以不写父bean的class属性,那么abstract就一定指定为true
2.4 spring对date类型属性的注入,直接set注入"2015-02-14"会出错,spring提供了两种方法注入http://www.yiibai.com/spring/spring-how-to-pass-a-date-into-bean-property-customdateeditor.html
1. 声明一个dateFormat bean,在“customer” Bean,引用 “dateFormat” bean作为一个工厂bean。该工厂方法将调用SimpleDateFormat.parse()自动转换成字符串Date对象。
<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
//自定义类customer
<bean id="customer" class="com.yiibai.common.Customer">
<property name="date">
<bean factory-bean="dateFormat" factory-method="parse">
<constructor-arg value="2015-12-31" />
</bean>
</property>
</bean>
第二种方法:
声明一个 CustomDateEditor 类将字符串转换成 java.util.Date。
<bean id="dateEditor"
class="org.springframework.beans.propertyeditors.CustomDateEditor">
<!--构造函数表示构造格式和是否为空-->
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</constructor-arg>
<constructor-arg value="true" />
</bean>
<!--并声明另一个“CustomEditorConfigurer”,使 Spring转换 bean 属性,其类型为java.util.Date-->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<ref local="dateEditor" />
</entry>
</map>
</property>
</bean>
<!---自定义类->
<bean id="customer" class="com.yiibai.common.Customer">
<property name="date" value="2015-12-31" />
</bean>
2.3 自动装配(不常用,后面有更直观的技术)
SpringIOC不用set注入和构造器注入,一样可以依赖注入,在创建bean时,可以根据类型或者名称,从容器中找到匹配的bean,设置给这个bean属性,在bean中用autowire属性指定装配规则,默认no,可以选择byName byType constructor autodetect(有默认构造器选择constructor,不然选择byType)
实际项目中,可以给一个bean1声明接口,给另一个bean2注入的是这个bean的实现类,若依赖的bean2发生改变,直接更改bean的实现类即可。
2.4springEL表达式
在spring配置文件中,获取其他bean或者集合的值,
1.#{beanid.属性} beanid是容器中bean的id,这个bean必须有get属性的方法,和EL表达式读取bean差不多。
2.如果要读取一个集合中的一个属性,也和EL差不多,#{beanid.listName[index]}
3.读取map集合的一个value,#{beanid.mapN.keyN}
4.读取proeprties的属性值,#{id.propertyName}
5.使用其他bean的方法 #{beanId.method()}
6.支持运算符:+-*%/^
7.springel表达式中+还可以当做字符串连接符 :#{beanid.name+"你好"}
8.支持比较运算符:<<=>>===!= le ge lt gt eq #{beaid.age gt 20}
9.and or not #{shop.isable and shop.name=='shop'} #{not shop.isabel}
10.正则表达式 #{shop.name matches '[a-zA-z]{2,4}'}
11.静态方法 T()方式 #{T(java.lang.Math).random()*10}
2.5spring中的后置处理器:在spring容器中对所有的bean,调用init初始化方法前后的处理,实现BeanPostProcessor接口即可。
public class Proo implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
if(!s.equals("testt")){
MyTest o1 = (MyTest) o;
System.out.println("这是mytest的前置通知");
}
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
if(s.equals("testt")){
MyTest o1 = (MyTest) o;
System.out.println("这是mytest的后置通知");
}
return o;
}
}
3方式二:基于注解的配置(不需要set方法了) 注解连线在默认情况下在 Spring 容器中不打开。再spring中配置 <context:annotation-config/> 这个注解激活@PostConstruct @PreDestroy @AutoWire @Resource等
3.1 组件扫描(使用了<context:component-scan base-package=””/>,就不用再写<context:annotation-config/>,前者包含了后者的功能。)
Spring容器启动之后,扫描配置文件,如果配置文件中有下面的组件扫描,则容器会扫描指定包极其子包下面的类,多个包之间用,分隔 -->如果该类包含了特定的注解,则容器会将这个类纳入容器进行管理(相当于在配置文件中配置了一个bean),默认这个类的id是首字母小写的类名,如果想更改id,在注解后添加(“newId”)
<context:component-scan base-package=””/>
注解标记
@Component 通用
@Repository 持久层
@Service 业务层
@Controller 控制层
类的作用域:在类名前加上 @Scope(“prototype”),可以保证线程安全,每次使用都是新的对象
Bean的声明周期: 在init方法前加上注解 @PostConstruct , 在destroy方法前加上 @PreDestroy 这个不属于spring,在xml添加<context:annotatin-config/>启动这个注解,有组件扫描就不用。
延迟加载:加上注解 @Lazy(true)
DI依赖注入:
-
Autowired默认是bytype方式,可能有多个bean合适,所以在参数中增添@qualifier指定要注入bean的Id按名称注入
方式一:在set方法前添加注解
@Autowired
public void setWaiter(@Qualifier("wt") Waiter waiter) {
this.waiter = waiter;}
方式二:也可以在属性前加,这时对应的set方法可以不要
@Autowired
@Qualifier("wt")
private Waiter waiter;
方式三:Autowired的构造器注入方式:
@Autowired
public Hotel(@Qualifier("wt") Waiter waiter){
System.out.println("hotel的有参构造器");
}
- Resource注入,默认根据byName方式注入,根据属性名或者色图参数里的参数名找bean,找不到就根据属性名前的类型找bean,一般所以后面跟一个name,根据resource指定的name找bean。 用在set方法前或者属性字段前,写在属性名前就不用写setter方法。
@Resource(name="wt") 这是java中的一个jar包
public void setWaiter(Waiter waiter) {
System.out.println("manager的注入方法");
this.waiter = waiter;
}
@Resource(name="wt")
private Waiter waiter;
使用注解的方式使用spring表达式读取值,写在属性前或者set方法前
@Value("#{id.属性值}")
也可以使用@Value注解给属性赋值,写在属性前或者set方法前
@Value("${name}")
private String pageSize;
spring的EL表达式:
<import>标签引入其他spring配置文件
注意:spring有一个依赖包:commons-logging-1.1.1.jar
注意:当类中只有一个参数的构造器,不用显示注入,他会自动注入该bean
@Data
@Component
public class Student {
private Book book;
public Student(Book book){
this.book = book;
}
}
@Data
@Component
public class Book {
@Value("zhouyang")
private String name;
}
@Resource
private Student student;
@org.junit.Test
public void test(){
System.out.println(student);
}
这是可以直接注入的。
5.方式三:不是用xml的配置类,为了消除xml配置文件
5.1@Configuration 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
@Configuration
public class SpringConfiguration {
}
5.2@ComponentScan 扫描类,作用同<context:component-scan base-package="com.zy"/>
@Configuration
@ComponentScan(("com.zy"))
public class SpringConfiguration {
}
5.3@Bean 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。没写name属性就默认用方法的名称作为bean的id
@Configuration
@ComponentScan(("com.zy"))
public class SpringConfiguration {
@Bean(name="student")
public Student student(){
return new Student();}
}
5.4@PropertySource 用于加载.properties 文件中的配置。通常与@Value一起使用, properties配置文件中的值存储到Spring的 Environment中
@Configuration
@ComponentScan(("com.zy"))
@PropertySource("classPath:db.Properties")
public class SpringConfiguration {
@Vaule("${name})
private string name;
@Bean(name="student")
public Student student(){
Studnet student = new Student();
student.setName(name);
return student;
;}
}
5.5 @PropertySources 功能同@PropertiSource,配置多文件
@PropertySources({
@PropertySource("classpath:config.properties"),
@PropertySource("classpath:db.properties")
})
5.6@Import 用于导入其他配置类或者普通类,在引入其他配置类时,可以不用再写@Configuration 注解。写上也没问题
导入配置类
@Configuration
@ComponentScan(basePackages = "com.itheima.spring")
@Import({ JdbcConfig.class})
public class SpringConfiguration {
}
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig{
}
导入普通类,把该类加入容器中
public class TestA(){}
@Configuration
@ComponentScan(basePackages = "com.itheima.spring")
@Import({ JdbcConfig.class})
public class SpringConfiguration {
}
5.7@Profile 指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件; dev test master
1) 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
2) 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
private String driverClass;
@Profile("default")
@Bean("test")
public DataSource testDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("dev")
@Bean("dev")
public DataSource devDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("master")
@Bean("master")
public DataSource masterDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String driverClass = resolver.resolveStringValue("${db.driverClass}");
this.driverClass = driverClass;
}
}
public class IOCTestProfile {
//1. 使用命令行动态参数:在虚拟机参数位置加载 -Dspring.profiles.active=test
//2. 使用代码的方式激活某种环境;
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
//1. 创建一个applicationContext
//2. 设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev","master");
//3. 注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4. 启动刷新容器
applicationContext.refresh();
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
System.out.println(Arrays.toString(beanNamesForType));
applicationContext.close();
}
5.8 @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。
1.写在配置类上,表示配置类所有的bean满足条件加入容器
2.写在@Bean上,该bean满足条件加入容器
@Configuration
public class BeanConfig {
@Bean(name = "bill")
@Conditional({LinuxCondition.class})
public Person person1(){
return new Person("Bill Gates",62);
}
//LinuxCondition实现了Condition接口,满足mathes方法返回true,该bean加入容器
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}}
5.9 @Scope @Lazy登注解写在@Bean这里
5.10 通过注解获取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
5.11 xml和javaconfig相互引用
- xml中引入其他xml配置文件 :<import resource =“classpath:other.xml”>
- xml引入javaconfig,当做一个bean, <bean id="config" class="Config">
- javaconfig中引入xml配置文件
@Configuration
@ImportResource("classpath:applicationContext.xml")
public class BeanConfig {}
6.spring Junit测试,导入jar包,
@ContextConfiguration 注解:
locations 属性:用于指定配置文件的位置。如果是类路径下,需要用 classpath:表明
classes 属性:用于指定注解的类。当不使用 xml 配置时,需要用此属性指定注解类的位置。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
@Resource
private Student student;
}
7.spring依赖检查
方式一:xml注册
<bean id="" class="" depends-on="car,student"></bean>
写依赖的beanid,会在当前bean实例化之前创建好,写多个依赖用逗号
方式二:注解检查
在set方法上添加@required注解
在xml中注册 或者添加 <context:annotation-config/>有mvc注解就不需要

浙公网安备 33010602011771号