Spring4
- Spring javaEE开发一站式框架
- web层:SpringMVC
- Service层:Spring的Bean管理(IoC)、Spring声明式事务
- Dao层:Spring的jdbc模板。Spring的ORM模块用于整合其他的持久层框架
SpringIOC
IoC(控制反转):将对象的创建权交给Spring
作用:用于解耦,一般分为两种类型: 依赖注入(DI,应用更广泛)和依赖查找
IoC xml开发
工厂+反射+配置文件 实现程序的解耦
<?xml version="1.0" encoding="UTF-8"?>
<!--引入beans的约束-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="UserDao" class="com.m.spring4.dao.impl.UserDaoImpl"></bean>
</beans>
//创建Spring的工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao=(UserDao)applicationContext.getBean("UserDao");
userDao.save();
DI
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--构造方法属性注入-->
<bean id="Car" class="com.m.spring4.dao.Car">
<constructor-arg name="name" value="宝马"/>
<constructor-arg name="price" value="800000"/>
</bean>
<!--set方法属性注入--><!--value普通属性 ref对象属性-->
<bean id="UserDao" class="com.m.spring4.dao.impl.UserDaoImpl" >
<property name="name" value="张三"/>
<property name="car" ref="Car"/>
</bean>
<!--配置init 和destory 方法-->
<bean id="" class="" init-method="init" destory-method="destory"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="Car" class="com.m.spring4.dao.Car">
<constructor-arg name="name" value="宝马"/>
<constructor-arg name="price" value="800000"/>
</bean>
<bean id="UserDao" class="com.m.spring4.dao.impl.UserDaoImpl" p:name="张三" p:car-ref="Car">
</bean>
</beans>
SpEL
SpEL的属性注入(Spring3.0之后) Spring表达式语言
语言:#{SpEL}
name value形式
value可以是 对象、对象的属性、方法或''
注入数组类型
<bean>
<!-- 数组类型 -->
<property name="arrs">
<list>
<value>王东</value>
<value>赵洪</value>
<value>李冠希</value>
</list>
</property>
<!-- 注入list集合 -->
<property name="list">
<list>
<value>李兵</value>
<value>赵如何</value>
<value>邓凤</value>
</list>
</property>
<!-- 注入set集合 -->
<property name="set">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</set>
</property></bean>
IoC注解开发
引入约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 使用IoC的注解开发,配置组件扫描 (扫描类上的注解)(哪些包下的类要使用注解)-->
<context:component-scan base-package="com.m.spring4"></context:component-scan>
<!--在没有扫描的情况下,使用属性注入的注解 @Resource@Value@Autowired@Qualifier-->
<context:annotation-config/>
</beans>
/*
相当于在xml配置
<bean id="userDao" class="com.m.spring4.dao.impl.UserDaoImpl"></bean>
*/
@Component("userDao")
public class UserDaoImpl implements UserDao{
/*
注解方式设置属性的值,可以没有set方法
如果有set方法注解写到set方法上。
如果没有set方法,注解写到属性上。
*/
@value("张三")
private String name;
@Autowired
@Qualifier(value="car类的组件名")
private Car car;
}
IoC注解详解
1.@Component(""):组件
- 修饰一个类,将这个类交给Spring管理
- 有三个衍生注解:@Controller (Web层) @Service (service层) @Reposition(dao层)
2.属性注入的注解
普通属性
@Value("") 设置普通属性的值
对象类型属性
@Autowired 设置对象类型的属性的值(按照类型完成属性的注入)
@Qualifier (value="") 为了让其按照名称完成属性的注入
@Resouce(name="")用于替代@Autowired+@Qualifer
3.生命周期相关
初始化方法上的注解@PostConstruct
销毁方法上的注解@PreDestory
相当于xml中的init-method和destory-method
4.Bean作用范围
@Scope("singleton/prototype/request/session/globalsession")
Spring AOP
面向切面编程 Aspect Oriented Programming
采用了横向抽取机制代替了传统的纵向继承
1.Spring底层的AOP实现原理
动态代理:
JDK动态代理:只能对实现了接口的类产生代理
Cglib动态代理(类似于javassist的第三方代理技术):对没有实现接口的类产生代理对象,生成子类对象
AOP xml开发
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
<!-- 配置目标对象(Target): -->
<bean id="productDao" class="com.m.spring4.demo3.ProductDaoImpl"/>
<!-- 切面类 交给Spring管理 -->
<bean id="myAspectXml" class="com.m.spring4.demo3.MyAspectXml"/>
<!-- 通过 AOP的配置对目标类产生代理-->
<aop:config>
<!-- expression配置哪些类的那些方法需要增强 -->
<aop:pointcut expression="execution(* com.m.spring4.demo3.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* com.m.spring4.demo3.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* com.m.spring4.demo3.ProductDaoImpl.update(..))" id="pointcut3"/>
<!-- 配置切面 -->
<!-- 前置通知 -->
<aop:aspect ref="myAspectXml">
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>
<!-- 后置通知 -->
<aop:aspect ref="myAspectXml">
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
</aop:aspect>
<aop:aspect ref="myAspectXml">
<aop:around method="around" pointcut-ref="pointcut3"/>
</aop:aspect>
</aop:config>
</beans>
public class MyAspectXml {
/**
* 前置通知-权限校验
*/
public void checkPri(JoinPoint joinpoint) {
System.out.println("权限校验。。打印连接点信息"+joinpoint);
}
/**
* 后置通知-写日志
*/
public void writeLog(Object result) {
System.out.println("日志记录。。返回值:"+result);
}
/**
* 环绕通知-性能监控
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("环绕前通知。。");
Object obj=joinpoint.proceed();//相当于执行目标程序
System.out.println("环绕后通知。。");
return obj;
}
}
Spring通知类型
- 前置通知:目标方法执行之前
可以获得切入点信息
- 后置通知:目标方法执行之后
可以获得方法的返回值
- 环绕通知:在目标方法执行之前和之后进行操作
环绕通知可以阻止目标方法的执行
-
异常抛出通知:在程序抛出异常的时候,进行操作
-
最终通知:无论代码是否有异常,总会执行。
-
引介通知
切入点表达式(expression)写法:
>execution([访问修饰符] 方法返回值 包名.类名.方法名(参数))
>
>通配符*
>
>..
>
>+
基于AspectJ的注解开发
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 在配置文件中开启注解的AOP开发 -->
<aop:aspectj-autoproxy/>
<!-- target -->
<bean id="orderDao" class="com.m.spring4.demo4.OrderDao"/>
<!-- 切面类 -->
<bean id="myAspectAnno" class="com.m.spring4.demo4.MyAspectAnno"/>
</beans>
//切面类
@Aspect
public class MyAspectAnno {
@Before(value="execution(* com.m.spring4.demo4.OrderDao.save(..))")
public void before() {
System.out.println("前置增强==");
}
}
//使用切入点注解
@Aspect
public class MyAspectAnno {
@Before(value="MyAspectAnno.pointcut1()")
public void before() {
System.out.println("前置增强==");
}
//切入点注解
@Pointcut("execution(* com.m.spring4.demo4.OrderDao.save(..))")
public void pointcut1(){}
}
注解
定义切面类的注解
@Aspect
通知类型
@Before 前置通知
@AfterRunning 后置通知
@Around 环绕通知
@AfterThrowing 异常抛出后通知
@After 最终通知
@Pointcut 定义切入点的注解
Spring的工厂类
-
BeanFactory 老版本的工厂类: 调用getBean时,才会生成Bean的实例
-
ApplicationContext 新版本的工厂类,继承了BeanFactory: 加载配置文件时就生成Bean的实例
有两个具体的实现类
- FileSystemApplicactionContext 加载类路径下的配置文件
- ClassPathXmlApplicationContext 加载文件系统下的配置文件
加载多个配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("1.xml","2.xml")
在一个配置文件中引入其他配置文件
<import resource="applicationContext2.xml"/>
JDBC Template
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--配置Spring内置连接池-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///store?useSSL=false" />
<property name="username" value="root" />
<property name="password" value="Gepoint" />
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
<!-- 配置DBCP连接池 -->
<!--引入jar包
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///store?useSSL=false" />
<property name="username" value="root" />
<property name="password" value="Gepoint" />
</bean>
C3P0连接池
<!-- 配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///store?useSSL=false"></property>
<property name="user" value="root" />
<property name="password" value="Gepoint" />
</bean>
常用方式:外部属性文件
<!--
//jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///store?useSSL=false
jdbc.username=root
jdbc.password=Gepoint
-->
<!-- 配置C3P0连接池 -->
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
Spring的事务管理
Spring事务管理API
平台事务管理器根据事务定义信息进行事务的管理,,在事务管理的过程中,产生的各种状态记录到事务状态的对象中。
PlatformTranscationManager
平台事务管理器
实现类:
DataSourceTranscationManager:底层使用jdbc管理事务
HibernateTranscationManager:底层使用hibernate管理事务
TranscationDefinition
事务定义信息
用于定义事务相关的信息:隔离级别、超时信息、传播行为、是否只读
TranscationStatus
事务的状态
用于记录在事务管理过程中,事务的状态对象。
事务的传播行为
事务应该加到业务层
事务的传播行为主要用来解决业务层方法相互调用的问题。
Spring提供了7种事务的传播行为:
事务管理
编程式事务管理
1.配置平台事务管理器
2.配置事务的管理模板类
3.在业务层注入事务管理的模板
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Dao -->
<bean id="accountDao" class="com.m.spring4.tx1.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Service -->
<bean id="accountService" class="com.m.spring4.tx1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<!--3.在业务层中注入事务管理模板-->
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
<!-- JDBC -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 1.配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2.配置事务管理模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
</beans>
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
//注入事务管理的模板
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public void transfer(String from,String to,Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
// TODO Auto-generated method stub
accountDao.outMoney(from, money);
int d=1/0;
accountDao.inMoney(to, money);
}
}) ;
}
}
声明式事务管理
通过配置实现 --AOP
<!-- 配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务的增强 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- AOP的配置 -->
<aop:config>
<aop:pointcut expression="execution(* com.m.spring4.tx1.AccountServiceImpl.*(..))" id="pointcut1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>