一、准备工作
1.创建Maven的java项目。
2.导入java项目的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
3.编写applicationContext.xml 文件
src->main->resources->applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
</beans>
二、使用spring创建bean对象
不需要再手动new对象
1.向applicationContext.xml配置文件中加入bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
<bean id="stu" class="demo.bean.Student">
<property name="name" value="小明"></property>
<property name="age" value="18"></property>
</bean>
</beans>
2.通过spring的方式获取对象,只能通过空参构造创建
@Test
public void test2(){ // 通过spring的方式获取对象,调用方法
//1 加载spring的配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2 通过spring的方式获取对象
Student stu = ac.getBean("stu",Student.class);
/*
* stu对象是通过ac的getBean方式获取到的。那么这个stu对象就是由spring框架负责创建的
*
* 当spring的配置文件applicationContext.xml文件加载后。spring读取 <bean id="" class>的配置
* spring就会根据 class中配置的类全名,反射方式创建对象,在读取<property>中的内容完成赋值
*
* 把创建好的对象放到一个容器(类似于map)中储存起来 -------> key:配置时的id value就是spring创建的对象
*
* ac.getBean(配置时的id值) 就获取到的容器中储存对象。
* */
System.out.println(stu.getId()+"\t"+stu.getName()+"\t"+stu.getAge());
stu.sayHello();
}
3.spring创建对象是否单例
默认是单例,也可更改,加上scope属性
三、SpringIOC 讲解
IOC控制反转
* IOC Inversion of Control 控制反转。
*
* 控制反转就是只对象控制权的反转。
* 在没有使用IOC之前,对象的创建都是由应用程序来负责的(程序员在代码中自己new)
* 在使用了Spring(spring的IOC)后,对象的创建交给了spring(对象由spring负责创建)
* 这种对象的控制器由应用程序转到spring的现象就叫做控制反转。
DI依赖注入
依赖注入(Dependency Injection)
* 类与类的关系:
*
* 1 继承关系 class A extends B
* 2 关联关系
* class A{
* }
*
* class B{
* private A a;
* }
*
* B类中的成员变量是A类型。 A类和B类是关联关系
*
* 3 依赖关系
*
* Class C{
*
* }
*
* class D{
* public void fun(C c){
* }
* }
*
* D类中的方法使用C类型。D类和C类就是依赖关系。D依赖C
*
-
要讲解的Spring中依赖注入的依赖是广义上的依赖。 只要A类中使用了B类,就说A类依赖B类型
-
依赖注入: 不使用spring之前,依赖的对象也是由应用程序来控制(自己new)
-
使用spring之后,依赖的对象靠spring来注入!!!
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,由spring来创建对象,实现对象之间的解耦。
spring的工厂
BeanFactory 和ApplicationContext的区别:
1.ApplicationContext是BeanFactory 的子接口,比BeanFactory 拥有更多功能。
2.创建对象的时机不同:
ApplicationContext是加载完spring的配置文件后,就创建对象。
BeanFactory 是调用getBean时才创建对象。
四、属性注入
set注入
bean中必须有无参构造,属性有set方法
<bean id="stu" class="demo.bean.Student" >
<property name="name" value="小明"></property>
<property name="age" value="18"></property>
</bean>
构造器注入
bean中必须有有参构造,可以加入get方法获取属性值
<bean id="car" class="demo.bean.Car">
<constructor-arg name="name" value="宝马"></constructor-arg>
<constructor-arg name="color" value="red"></constructor-arg>
</bean>
复杂类型注入,属于set注入
private String[] arr;
private List list;
private Set set;
private Map map;
private Properties prop;
<bean id="array" class="demo.bean.Array">
<!--数组-->
<property name="arr">
<array>
<value>arr1</value>
<value>arr2</value>
<value>arr3</value>
</array>
</property>
<!--list集合-->
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<!--set集合-->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
</set>
</property>
<!--map集合-->
<property name="map">
<map>
<entry key="map1" value="111"></entry>
<entry key="map2" value="222"></entry>
<entry key="map3" value="333"></entry>
</map>
</property>
<!--Properties配置文件-->
<property name="prop">
<props>
<prop key="prop1">111</prop>
<prop key="prop2">222</prop>
<prop key="prop3">333</prop>
</props>
</property>
</bean>
五、SpringAOP 讲解
面向切面编程Aspect Oriented Programming
AOP名词解释
目标(Target)
没有增强功能之前的代码(要被增强,要增加新功能)
切面(Aspect)
要增强的新功能(方法),放在切面中
织入(Weaving)
动词,把目标和切面切在一起的动作(把切面切入到目标中)
代理(Proxy)
目标和切面织到一起后形成的新对象(即具有目标的原有功能,有具体增强的新功能)
切入点(PointCut)
目标中所有可以被切面切的地方(一般是目标中的方法)
连接点(JoinPoint)
当切面真的来切这个切入点了,这个切入点就变成了连接点
通知(Advice)
告诉切面在哪里(在目标方法调用之前、目标方法调用之后、环绕、抛异常时)去切
添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
</dependency>
创建切面类
public class Aop {
public void method(){
System.out.println("切面。。。。。。");
}
}
配置切入
<bean id="aop" class="demo.aspect.Aop"></bean>
<!--配置切入-->
<aop:config>
<!--切入点-->
<aop:pointcut id="allservice" expression="execution(* demo.service.StudentServiceImpl.*(..))"/>
<!--切面-->
<aop:aspect ref="aop">
<aop:before method="method" pointcut-ref="allservice"></aop:before>
</aop:aspect>
</aop:config>
方法命名add*(…):所有以add开头的方法
效果
通知说明
Around通知较为特殊,需要在切面方法中放行目标方法 pjp.proceed();
<aop:around method="myAround" pointcut-ref="allServiceMethod"/>
放行目标方法
public void myAround(ProceedingJoinPoint pjp){
System.out.println("around 环绕 ,在目标方式之前执行###");
try {
pjp.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 调用目标方法
System.out.println("around 环绕 ,在目标方式之后执行####");
}
获取连接点
public class Aop {
public void method(JoinPoint jp){
jp.getArgs(); // 获取被切的切入点(方法)的参数
String name = jp.getSignature().getName(); //获取被切的切入点(方法)的名字
}
六、spring整合JDBC
1.添加依赖
除了通用的IOC依赖,还有以下依赖
<!-- druid mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- spring-jdbc spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
2.书写dao
public class AddUserImpl implements AddUser{
JdbcTemplate jt;
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public int add(User user) {
String sql="insert into users values(null,?,?);";
int update = jt.update(sql, user.getUsername(), user.getPassword());
return update;
}
}
3.书写配置文件
<!--配置持久层操作对象-->
<bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds"></property>
</bean>
<!--配置持久层-->
<bean id="userdao" class="demo.dao.AddUserImpl">
<property name="jt" ref="jdbctemplate"></property>
</bean>
<!--配置数据源-->
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql:///test"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
七、spring注解方式IOC开发
1.添加配置文件
<!--开启spring注解方式-->
<context:annotation-config></context:annotation-config>
<!--设置扫描路径-->
<!--spring会为扫描路径下所有添加了@Component注解的类创建spring的bean-->
<context:component-scan base-package="demo"></context:component-scan>
<!--开启AOP注解-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2.类上添加注解
@Component//bean的id默认是类名首字母小写
//@Component("aa")
@Scope("prototype")
public class Transaction {
@Autowired//自动装配,把类型匹配的bean注入
private Car c;
@Autowired
private Ship s;
public Car getC() {
return c;
}
public void setC(Car c) {
this.c = c;
}
public Ship getS() {
return s;
}
public void setS(Ship s) {
this.s = s;
}
}
3.常用注解
-
@Component :添加了这个注解的类会被spring扫描当成 bean来处理
可以设置bean的id : @Component(“起名字bean的id”)
也可以不设置bean的id 默认就是类名首字母变小写 -
@Autowired : 自动装配(按类型)
问题:当多个类型符合时,将无法注入
解决:
-
@Scope(“prototype”) 更改单例为每次getBean创建新的对象
-
Spring还提供了以下几个注解来替代 @Component
@Controller 一般加在控制层
@Service 一般加在业务层
@Repository 一般加在持久层
作用和@Component完全相同(可能会在以后的版本中有不同)
八、注解方式AOP开发
1.添加配置文件
<!-- 开启注解方式的aop -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2.配置切面注解
@Component
@Aspect//指定切面
public class log {
//方法一
@Pointcut("execution(* demo.service.*.*(..))")
public void anyMethod(){//写一个随意的方法,目的引入切入点
}
//方法二
@Before("execution(* demo.service.*.*(..))")//直接指定切入点
public void before(){
System.out.println("before............");
}
@After("execution(* demo.service.*.*(..))")
public void after(){
System.out.println("after............");
}
@AfterReturning("anyMethod()")//使用上面的方法名指定切入点
public void afterReturn(){
System.out.println("afterReturning............");
}
@Around("execution(* demo.service.*.*(..))")
public void around(ProceedingJoinPoint jp){
System.out.println("around 1----------");
try {
jp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("around 2------------");
}
}
3.切面注解的两种方式对比
方式一固定,一旦修改就都改变。
方式二较为灵活。
九、修改ApplicationContext对象
1.添加依赖
2.设置监听器
监听器ContextLoaderListener的init方法,随着服务器启动,servletContext的创建而执行,让servletContext加载context-param中的参数,加载xml,生成了ApplicationContext对象。
3.获取applicationContext对象
避免每次都new,一直使用servletContext中的ApplicationContext
十、spring事务
1.配置文件方式事务开发
配置事务管理器和切入点
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"></bean>
<!-- 配置事务管理器(切面) 目标就是service-->
<!-- spring针对不同的持久层提供了不同的事务管理器(切面) jdbc:DataSourceTransactionManager-->
<!-- 事务管理器可以控制事务的提交和回滚 需要操作数据库 需要把dataSource注入给事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!-- 定义事务的传播规则-->
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="zhuanzhang" propagation="REQUIRED" no-rollback-for="java.lang.ArithmeticException" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allServiceMethods" expression="execution(* com.offcn.service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"></aop:advisor>
</aop:config>
2.事务的传播规则
3.回滚规则
默认情况下spring的事务管理是碰见异常就回滚
no-rollback-for:碰见这种异常不回滚,其他异常都回滚
4.注解方式事务开发
1.配置事务管理器,开启注解方式事务
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"></bean>
<!-- 注解方式的事务管理,事务管理器还是需要配置-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!--引入事务管理器-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" proxy-target-class="true"></tx:annotation-driven>
2.代码
使用@Transactional注解: 可以加在类上,也可以加在方法
加在类上,这个类中的所有public修饰的方法都会被事务管理
加在方法上,就是这个具体的方法会被事务管理
@Service("accountService")
//@Transactional(propagation = Propagation.REQUIRED) // 这种配置,对类中的每个方法都起作用
public class AccountServiceImpl implements AccountService {
@Transactional(propagation = Propagation.REQUIRED) // 加在方法上,只对当前方法起作用
public String zhuanzhang(int outId, int inId, int money) {
5.配置文件方式和注解方式比较
- 配置文件方式可以一次对指定的所有切入点添加事务。
- 注解方式需要挨个在每个类上添加,如果类多的情况下,显然麻烦。