Spring框架
spring的优点:
1、方便解耦,简化开发
Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。
2、AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
3、声明式事物的支持
只需要通过配置就可以完成对事物的管理,而无需手动编程。
4、方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序
5、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis等)的直接支持。
6、降低JavaEE API的使用难度
Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,是这些API应用难度大大降低
spring下载地址
Spring 4.2官方下载地址
面向接口编程:
如果直接用接口去new一个实现类那么它就会与业务层产生联系,(opc原则)所以有了Spring的工厂模式,为解决工厂与接口之间的耦合有了:工厂+反射+配置文件 如:
<bean id="us" class="com.dao.userServiceImpl">
Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。
Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new
一个对象,而是让Spring框架帮你来完成这一切。
package com.spring2.ioc.demo1;
public class UserServiceImpl implements UserService{
@Override
public void sayHello() {
System.out.println("Hello Spring");
}
}
//Spring配置文件:
<?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">
<!--UserService的创建权交给了Spring-->
<bean id="userService1" class="com.spring2.ioc.demo1.UserServiceImpl">
<!--设置属性-->
<property name="name" value="张三"/>
</bean>
</beans>
//使用:
@Test
/*
* 用ClassPathXmlApplicationContext读取磁盘的配置文件
* */
public void dome2(){
//创建Spring的工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获取类
UserService userService=(UserService) applicationContext.getBean("userService1");
userService.sayHello();
}
@Test
/*
* 用FileSystemXmlApplicationContext读取磁盘系统中的配置文件
* */
public void demo3(){
//创建Spring的工厂
ApplicationContext applicationContext1=new FileSystemXmlApplicationContext("D:\\Javaprogram\\spring2_ico\\src\\main\\resources\\applicationContext.xml");
UserService userService=(UserService) applicationContext1.getBean("userService1");
userService.sayHello();
}
/*
*1、FileSystemXmlApplicationContext读取磁盘系统中的配置文件
*2、ClassPathXmlApplicationContext在一个工程读取配置文件
*/
/*
* 传统方式的工厂类:BeanFactory
* BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
* */
注:
<!-- 引入其它spring配置文件 -->
<import resource="spring/bean/applicationContext2.xml"/>
Spring IOC:
IOC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理
DI Dependency Injection 依赖注入的概念,就是在Spring创建这个对象的过程中,将这个对象依赖的属性注入进去。
Spring的Bean管理(XML方式):
Spring的Bean管理(XML方式):
一、三种实例化Bean的方式:
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--构造方式-->
<bean id="bean1" class="com.spring2.ioc.demo2.Bean1"></bean>
<!--第二种静态方式-->
<bean id="bean2" class="com.spring2.ioc.demo2.Bean2Faction" factory-method="createBean2"></bean>
<!--第三种工厂方式实例化-->
<bean id="bean3Faction" class="com.spring2.ioc.demo2.Bean3Faction"/>
<bean id="bean3" factory-bean="bean3Faction" factory-method="createBean3"/>
</beans>
(一)、id和 name、class
—— 一般情况下,装配一个Bean时,痛殴制定一个id属性作为Bean的名称
—— id属性在IOC容器中必须是唯一的(name和id的作用是一样的,但id中不能有特殊字符,name中可包含特殊字符,4.0以前name可以重复)
—— 如果Bean的名称中含有特殊字符,就需要使用name属性
—— class用于设置一个类的完全路径,主要作用是IOC容器生产类的实例。
Bean的作用域:
scope属性默认是:singleton
Spring容器中Bean的生命周期:
1、Spring初始化bean或销毁bean时,有时需要做一些处理工作,因此spring可以在创建和销
毁bean的时候调用bean的两个生命周期方法。
当bean被载入到容器的时候调用init,当删除的时候调用destroy(scope=singleton有效)。
注:一共有十一个过程,
1、实例化对象
2、设置(封装 )属性
3、如果Bean实现BeanNameAware 执行setBeanName
4、如果Bean实现BeanFactoryAware或者ApplicationContextAware设置工厂setBeanFactory或者上下文对象setApplicationContext
5、如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization(在初始化之前就执行的方法)
(三和四需要去配置一下bean但可以不用配id)
6、如果Bean实现I逆天例子那个Bean执行afterPropertiesSet(鼠标设置完成之后时执行)
7、调用指定初始化方法init
8、如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
9、执行业务处理(自己定义的方法)
10、如果Bean实现DisposableBean执行destroy(spring销毁,接口:DisposableBean)
11、调用指定销毁方法customerDestroy
业务增加:
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化后执行的方法");
if ("UserDao".equals(beanName)){
Object proxy=Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("select".equals(method.getName())){
System.out.println("权限校验=============");
return method.invoke(bean,args);
}
return method.invoke(bean,args);
}
});
return proxy;
}
return bean;
}
Spring的属性注入:
对于类成员变量,注入方式有三种:
——构造函数注入
——属性setter方法注入
——接口注入
Spring支持前两种
一、Spring 的属性注入-构造方法注入:
1、通过构造方法注入Bean的属性或依赖的对象,它保证了Bean实例在实例化就可以使用。
2、构造器注入在元素里声明的属性。
<!--Bean的构造方法的属性注入========================-->
<bean id="user" class="com.spring2.ioc.demo4.User">
<constructor-arg name="name" value="小王八羔子"/>
<constructor-arg name="age" value="15"/>
</bean>
二、set方法注入:
shiyongset方法注入,在Spring配置文件中,通过设置注入的属性。对象注入用 ref
<!--Bean的set方法的属性注入========================-->
<bean id="psera" class="com.spring2.ioc.demo4.Psera">
<property name="name" value="网二"/>
<property name="age" value="45"/>
<property name="psera2" ref="psera2"/>
</bean>
<bean class="com.spring2.ioc.demo4.Psera2" id="psera2">
<property name="name2" value="小三"/>
</bean>
三、spring的属性注入-p名称空间:
——使用p命名空间
——为了简化XML文件配置,Spring从2.5开始引入一个新的p名称空间
——p:<属性名>=“XXX”引入常量值
——p:<属性名>-ref=“XXX” 引用其他Bean对象
//先要在头部加P空间
xmlns:p="http://www.springframework.org/schema/p"
<!--Bean的P标签属性注入========================-->
<bean id="psera" class="com.spring2.ioc.demo4.Psera" p:name="张三" p:age="18" p:psera2-ref="psera2"/>
<bean class="com.spring2.ioc.demo4.Psera2" id="psera2" p:name2="小二"/>
四、Spring的属性注入——SpELl注入
——SpELl:spring expression language,spring 表达式语言,对依赖注入进行简化
——语法:#{表达式}
——
如:
SpELl表达式语言:
语法:#{}
#{‘hello’}:使用字符串
#{beanId}:使用别一个bean
#{beanId.content.toUpperCase()}:使用指定名属性,并使用方法
#{T(java.lang.Math).PI}:使用静态字段或方法
<!--Bean的SpEl的属性注入========================-->
<bean class="com.spring2.ioc.demo4.Psera2" id="psera2">
<property name="name2" value="#{'小三'}"/>
</bean>
<bean id="psera" class="com.spring2.ioc.demo4.Psera">
<property name="name" value="#{'天翼'}"/>
<property name="age" value="#{45}"/>
<property name="psera2" value="#{psera2}"/>
</bean>
五、复杂类型的属性注入:
——数组类型的属性注入
——List集合类型的属性注入
——Set集合类型的属性注入
——Map集合类型的属性注入
——Properties类型的属性注入
<!--Bean的集合属性注入========================-->
<bean id="listss" class="com.spring2.ioc.demo4.List_var">
<!--数组-->
<property name="sts">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<!--List集合-->
<property name="list1">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<!--Map集合-->
<property name="maps">
<map>
<entry key="name" value="张力"></entry>
<entry key="age" value="18"></entry>
<entry key="sex" value="男"></entry>
</map>
</property>
<!--set集合-->
<property name="sets">
<set>
<value>sss</value>
<value>eee</value>
<value>ttt</value>
</set>
</property>
<!--props集合-->
<property name="props">
<props>
<prop key="user">123</prop>
<prop key="pws">1234</prop>
</props>
</property>
</bean>
Spring的注解方式:
需要注入命名空间:
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
一、Spring2.5 引入使用注解去定义Bean
——@Component 描述Spring框架中Bean(如果不描述,会直接用类名注入,只是会将类名第一个字母改为小写)
@Component("psera2")
二、除了@Component外,Spring提供了3个功能基本和@Component等效的注解
——@Repository用于对DAO实现类进行表注
——@Service用于对Service实现类进行表注
——@Controller用于对Controller实现类进行表注
注:这三个注解是为了让标注类本身的用途清晰,Spring在后续本版会对其增强
一般类型可以用:@Value(“值”)赋值
//有ser方法时必须在set方法上
@Value("汪汪")
private String name2;
——使用@Autowired进行自动注入
——@Autowired默认按照类型进行注入
—如果存在两个相同Bean类型相同,则按照名称注入
——@Autowired注入时可以针对成员变量或者ser方法
——通过@Autowired的required属性,设置一定要找到匹配的Bean
——使用@Qualifier指定注入Bean的名称
——Spring提供对JSR-250中定义@Resource标准注解的支持(等价于@Autowired和@Qualifier一起)
引用别的类(相当于实列化): @Autowired
@Autowired
private Psera2 psera2;
@Autowired
@Qualifier("psera22")
private Psera2 psera2;
@Resource(name="psera22")
private Psera2 psera2;
三、其它注解:
传统XML配置和注解配置混合使用:
——XML方式的优势:
- 结构清晰,易于阅读
——注解方式的优势:
- 开发便捷,属性注入方便
——XML与注解的整合开发
- 1、引入context命名空间
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
- 2、在配置文件中添加context:component-scan标签
只需要开启:注解扫描: <comtext:component-scan base-package=“扫描的范围”/>
<?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"
xmlns:comtext="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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启AspectJ的注解开发,自动代理=====-->
<aop:aspectj-autoproxy/>
<!--开启ioc注解-->
<comtext:component-scan base-package="com.spring.ioc.demo4"/>
</beans>
AOP(面向切面编程):
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
——AOP采取横向抽取机制,取代了传统纵向继承体系重复代码(性能监视、事务管理、安全检查、缓存)
一、什么是AOP
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
二、AOP相关术语
Joinpoint(连接点):所闻连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
Pointcut(切入点):所谓切入点是值我们要对哪些Joinpoint进行拦截的定义。
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以运行期为类动态地添加一些方法或Field。
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。
spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
三、代理:
1、JDK动态代理
这种JDK动态代理可以增强实现了接口的类
2、CGLIB生成代理:
——对于不使用接口的业务类,无法使用JDK动态代理。
——CGLIB采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题。
这种方式需要引入spring的核心jar包(beans、expression、core、context)
代理知识总结:
——Spring在运行期,生成动态代理对象,不需要特殊的编译器
——Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入
1、若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理
2、若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
——程序中应优先对接口创建代理,便于程序解耦维护
——标记为final的方法,不能被代理,因为无法进行覆盖
-JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
-CGLib是针对目标类生成子类,因此类或方法不能使用final
——spring只支持方法连接点,不提供属性连接点.
SpringAOP增强类型
——AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice
——Spring按照通知Advice在目标类方法的连接点位置,可以分为5类:
- 前置通知 org.springframework.aop.MethodBeforeAdvice
在目标方法执行前实施增强
- 后置通知 org.springframework.aop.AfterReturningAdvice
在目标方法执行后实施增强
- 环绕通知 org.aopalliance.intercept.MethodInterceptor
在目标方法执行前后实施增强
- 异常抛出通知 org.springframework.aop.ThrowsAdvice
在方法抛出异常后实施增强
- 引介通知 org.springframework.aop.IntroductionInterceptor
在目标类中添加一些新的方法和属性(一般不管这种,因为spring AOP只支持方法层面的增强)
SpringAOP切面类型:
—— Advisor:代表一半切面,Advice本身就是一个切面,对目标所有方法进行拦截
—— PointcutAdvisor:代表具有切点的切面,可以指定拦截目标哪些方法
—— IntroductionAdvisor:代表引介切面,针对引介通知而使用切面(这种一般不怎么用)
Advisor切面案例
要引入spring几个基本的jar包还要spring AOP联盟的包(aopalliance)加spring aop
spring为我们提供了一个类生成代理:
—— ProxyFactoryBean常用可配置属性
- target:代理的目标对象
- proxyInterfaces:代理要实现的接口
- 如果多个接口可以使用以下格式赋值:
…
- interceptorNames:需要织入目标的Advice
- proxyTargetClass:是否对类代理而不是接口,设置为true时,使用CGLib代理
- singleton:返回代理是否为单例,默认单例
- optimize:当设置为true时,强制使用CGLib
实现
一、普通Advisor
1、目标接口
public class UsermIp implements UserDao {
@Override
public void add() {
System.out.println("add");
}
@Override
public void updata() {
System.out.println("updata");
}
@Override
public void selcet() {
System.out.println("selcet");
}
@Override
public void del() {
System.out.println("del");
}
}
1、目标接口实现类
public class Mydavice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("前置增强==============");
}
}
3、spring配置文件
<?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="user" class="com.spring.ioc.demo.UsermIp"/>
<!--前置通知类型-->
<bean id="davice" class="com.spring.ioc.demo.Mydavice"/>
<!--AOP产生代理-->
<bean id="student" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目标类-->
<property name="target" ref="user"/>
<!--实现的的接口-->
<property name="proxyInterfaces" value="com.spring.ioc.UserDao"/>
<!--拦截的名称-->
<property name="interceptorNames" value="davice"/>
</bean>
</beans>
4、调用,测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:app.xml")
public class TestMothe {
// @Autowired
// @Qualifier(value = "user")
@Resource(name = "student")
private UserDao userDao;
@Test
public void test1(){
userDao.add();
userDao.selcet();
userDao.updata();
userDao.del();
}
}
注:
@RunWith(SpringJUnit4ClassRunner.class) ======= 测试要导入JUnit4和spring-text的jar包
@ContextConfiguration(“classpath:app.xml”) ======= ApplicationContext app=new ClassPathXmlApplicationContext(“app.xml”);
二、普通PointcutAdvisor
- 使用普通Advice作为切面,将对目标类所有方法进行拦截,不够灵活,在实际开发中常用 带有切点的切面
- 常用PointcutAdvisor 实现类
- DefaultPointcutAdvisor 最常用的切面类型,它可以通过任意Pointcut和Advice组合定义切面
- JdkRegexpMethodPointcut 构造正则表达式切点
1、目标类
public class CustomerDao {
public void find(){
System.out.println("查询用户");
}
public void save(){
System.out.println("保存用户");
}
public void uddate(){
System.out.println("修改用户");
}
public void del(){
System.out.println("删除用户");
}
}
2、通知(环绕通知)
/*
* 环绕通知
* */
public class MyAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("环绕前通知增强");
Object obj=methodInvocation.proceed();
System.out.println("环绕后通知增强");
return obj;
}
}
3、spring配置文件
<?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="customer" class="com.spring.ioc.demo2.CustomerDao"/>
<!--配置通知-->
<bean id="myaroundadvice" class="com.spring.ioc.demo2.MyAroundAdvice"/>
<!--配置切入点-->
<bean id="myaround" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--pattern中配置正则表达式:.任意字符 *任意次数-->
<!-- <property name="pattern" value=".*"/>-->
<!-- <property name="pattern" value=".*save.*"/>-->
<property name="patterns" value=".*save.*,.*del.*"/>
<property name="advice" ref="myaroundadvice"/>
</bean>
<!--配置产生代理-->
<bean id="mycustomer" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="customer"/>
<property name="proxyTargetClass" value="true"/>
<property name="interceptorNames" value="myaround"/>
</bean>
</beans>
4、调用是一样的
自动创建代理
- 前面的几种代理,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护巨大。
- 解决方案:自动创建代理
- BeanNameAutoProxyCreator根据Bean名称创建代理
- DefaultAdvisorAutoProxyCreator 根据Advice本身包含信息创建代理
- AnnottionAwareAspectJAutoProxyCreator 基于Bean中的AspectJ注解进行自动代理
一、基于Bean名称的自动代理(BeanNameAutoProxyCreator):
<?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="customerDao" class="com.spring.ioc.demo2.CustomerDao"/>
<bean id="UserDao" class="com.spring.ioc.demo.UsermIp"/>
<!--配置通知-->
<bean id="myaroundadvice" class="com.spring.ioc.demo2.MyAroundAdvice"/>
<bean id="myaroundadvice2" class="com.spring.ioc.demo.Mydavice"/>
<!--配置产生代理-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*Dao"/>//*通配符
<property name="interceptorNames" value="myaroundadvice"/>
</bean>
</beans>
二、可以配置切面点的(DefaultAdvisorAutoProxyCreator ):
<?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="customerDao" class="com.spring.ioc.demo2.CustomerDao"/>
<bean id="UserDao" class="com.spring.ioc.demo.UsermIp"/>
<!--配置通知-->
<bean id="myaroundadvice" class="com.spring.ioc.demo2.MyAroundAdvice"/>
<bean id="myaroundadvice2" class="com.spring.ioc.demo.Mydavice"/>
<!--配置切面-->
<bean id="myadvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="pattern" value="com.spring.ioc.demo2.CustomerDao.save"/>
<property name="advice" ref="myaroundadvice"/>
</bean>
<!--配置产生代理-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
</beans>
AspectJ的使用:
开启AOP注解: aop:aspectj-autoproxy/
- AepectJ是一个基于JAVA语言的AOP框架
- Spring2.0以后新增了对AspectJ切点表达式支持
- @AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
- 新版本Spring框架,建议使用AspectJ方式来开发AOP
- 使用AspectJ需要导入表Spring AOP和AspectJ相关jar包
- 如:
- spring-aop
- com.springsource.org.aopalliance
- spring-aspects
- com.springsource.org.aspectj.weaver
@AspectJ提供不同的通知类型
- @Before 前置通知,相当于BeforeAdvice
- @AfterReturning后置通知,相当于AfterReturningAdvice
- @Around 环绕通知,相当于MethodInterceptor(事务管理,功能最强的,能够阻止目标方法执行)
- @AfterThrowing 异常抛出通知,相当于ThrowAdvice
- @After 最终final通知,不管是否异常,该通知都会执行
- @DeclareParents 引介通知,相当于IntroductionInterceptdor(一般不用)
在通知中通过value属性定义切面
- 通过execution函数,可以定义切面的方法切入
- 语法:
- execution(<访问修饰符>?<放回类型><方法名>(<参数>)<异常>)
- 例如:
- 匹配所有类public方法 execution(public * *(…))
- 匹配指定包下所有类方法 execution(* com.imooc.dao.*(…))
- execution(* com.imooc.dao…*(…)) …*表示包、子孙包下所有类
- 匹配指定类所有方法 execution(* com.imooc.service.UserService.*(…))
- 匹配实现特定接口所有类方法
execution(* com.imooc.dao.GenericDAO+.*(…)) - 匹配所有save开头的方法 execution(* save*(…))
通过注解实现:
1、目标类:
package com.spring.ioc.demo4;
import org.springframework.stereotype.Component;
@Component(value = "user")
public class UserFmI {
public void add() {
System.out.println("add");
}
public void del() {
System.out.println("del");
}
public void update() {
System.out.println("update");
}
public void select() {
System.out.println("select");
}
}
2、切面类(通知类)
…
3、spring配置文件:
<?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"
xmlns:comtext="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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启AspectJ的注解开发,自动代理=====-->
<aop:aspectj-autoproxy/>
<!--开启ioc注解-->
<comtext:component-scan base-package="com.spring.ioc.demo4"/>
</beans>
一、@Before前置通知
- 可以在方法中传入JoinPoint对象,用来获取切点信息
@Before(value = "execution(* com.spring.ioc.demo4.UserFmI.*(..))")
public void aVoid(JoinPoint joinPoint){
System.out.println("前置通知"+joinPoint);
}
二、@AfterReturning前置通知
- 通过returning属性,可以定义方法放回值,作为参数
三、@Around环绕通知 - around方法的返回值就是目标代理方法执行返回值
- 参数为ProceedingJoinPoint 可以调用拦截目标方法执行
@Around("execution(* com.spring.ioc.demo4.UserFmI.select(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前置通知");
Object org=proceedingJoinPoint.proceed();//执行目标方法
System.out.println("环绕后置通知");
return org;
}
注意:如果不调用ProceedingJoinPoint的proceed方法,那么目标方法就被拦截了
四、@AfterThrowing异常抛出通知
- 通过设置throwing属性,可以设置发生异常对象参数
@AfterThrowing( value = "execution(* com.spring.ioc.demo4.UserFmI.del(..))",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知"+e.getMessage());
}
五、@After最终通知
- 无论是否出现异常,最终通知总是会被执行的
@After("execution(* com.spring.ioc.demo4.UserFmI.del(..))")
public void after1(){
System.out.println("最终通知");
}
通过@Pointcut为切点命名
- 在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义
- 切点方法:private void 无参数方法,方法名为切点名
- 当通知多个切点时,可以使用 || 进行连接
@Component(value = "advice")
@Aspect
public class Myadvice {
@Before(value = "cp1()")
public void aVoid(){
System.out.println("前置通知");
}
@AfterReturning( value = "cp()||cp1()",returning = "redd")
public void after(Object redd){
System.out.println("后置通知"+redd);
}
@Around("cp2()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前置通知");
Object org=proceedingJoinPoint.proceed();//执行目标方法
System.out.println("环绕后置通知");
return org;
}
@AfterThrowing( value = "cp3()",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知"+e.getMessage());
}
@After("cp3()")
public void after1(){
System.out.println("最终通知");
}
@Pointcut("execution(* com.spring.ioc.demo4.UserFmI.update())")
public void cp(){}
@Pointcut("execution(* com.spring.ioc.demo4.UserFmI.add())")
public void cp1(){}
@Pointcut("execution(* com.spring.ioc.demo4.UserFmI.select())")
public void cp2(){}
@Pointcut("execution(* com.spring.ioc.demo4.UserFmI.del())")
public void cp3(){}
}
通过XML实现
这就只贴spring配置文件了
<?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"
xmlns:comtext="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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--XML方式配置AOP-->
<!--配置目标类-->
<bean id="userIm" class="com.spring.ioc.demo5.CustromIm"/>
<!--配置切面类-->
<bean id="myadvice1" class="com.spring.ioc.demo5.Myadvice"/>
<!--AOP的相关配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pointcut1" expression="execution(* com.spring.ioc.demo5.CustromIm.*(..))"/>
<!--配置AOP的切面-->
<aop:aspect ref="myadvice1">
<!--前置通知-->
<aop:before method="after" pointcut-ref="pointcut1"/>//method是切面增强的方法,pointcut-ref是切入点(就是为谁服务)
<!--后置通知-->
<aop:after-returning method="after" pointcut-ref="pointcut1" returning=""/>//后置可以返回值;returning是返回参数名称
<!--环绕通知-->
<aop:around method="after" pointcut-ref="pointcut1"/>
<!--最终通知-->
<aop:after method="after" pointcut-ref="pointcut1"/>
<!--异常通知-->
<aop:after-throwing method="after" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
JDBC Template:
- 使用Spring组件JDBC Template简化持久化操作,它是在JDBC API之上提供的组件
一。创建项目:
- Maven
- MySQL驱动
- Spring组件(core、beans、context、aop)
- JDBC Template(jdbc、tx)
- Spring配置
- 数据源
- JDBC Template
1、要引入的jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>untitled5</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.22</version>
</dependency>
<!--spring组件jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!--JDBC、tx事务处理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!--测试包Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>Test</scope>
</dependency>
</dependencies>
</project>
2、spring配置:
<?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">
<!--连接数据库-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--驱动类-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!--数据库地址(一般会指定数据库的字符集(characterEncoding=utf-8"))-->
<property name="url" value="jdbc:mysql://localhost:3306/mylstu?characterEncoding=utf-8"/>
<!--数据库账号-->
<property name="username" value="root"/>
<!--数据库密码-->
<property name="password" value="123456"/>
</bean>
<!--配置Template工具-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
JDBC Template基本使用:
- execute方法(一般用它建表)
- update与batch Update方法(增删改)
- query与queryXXX方法(查询)
- call方法(调用存储过程的)
一、execute(一般用它建表)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class Test {
@Resource(name = "jdbcTemplate")
public JdbcTemplate jdbcTemplate;
@org.junit.Test
public void testExecute(){
/*
*通过JdbcTemplate的execute来执行DDL语句
* */
jdbcTemplate.execute("create table user1(id int,name varchar(20) )");
}
}
二、update与batch Update方法(增删改)
- Update方法
- 对数据进行增删改操作
Object[],Object…是传入的参数
例子:
- 对数据进行增删改操作
//Update
@org.junit.Test
public void testUpdate(){
String sql="insert into user1 values(?,?)";
jdbcTemplate.update(sql,new Object[]{1,"小明"});
}
- batch Update方法
- 批量增删改操作
例子:
- 批量增删改操作
//batchUpdate
@org.junit.Test
public void testbatchUpdate(){
String sql="insert into user1 values(?,?)";
List<Object[]> list=new ArrayList<Object[]>();
list.add(new Object[]{4,"小张"});
list.add(new Object[]{5,"老王"});
jdbcTemplate.batchUpdate(sql,list);
}
三、query与queryXXX方法(查询)
//query
@org.junit.Test
public void query(){
String sql="select count(*) from user1";
int sum=jdbcTemplate.queryForObject(sql,Integer.class);
System.out.println(sum);
}
//querylist
@org.junit.Test
public void querylist() {
String sql = "select name from user1 where id=?";
List<Object> sumlist = jdbcTemplate.queryForList(sql, Object.class, 1);
System.out.println(sumlist);
}
//querylist封装成类对象(匿名内类)
@org.junit.Test
public void querylistBeas() {
String sql = "select *from user1 where id>?";
List<UserBean> sumlistBean = jdbcTemplate.query(sql, new RowMapper<UserBean>() {
public UserBean mapRow(ResultSet resultSet, int i) throws SQLException {
UserBean bean=new UserBean();
bean.setId(resultSet.getInt("id"));
bean.setName(resultSet.getString("name"));
return bean;
}
}, 0);
System.out.println(sumlistBean);
}
//考虑代码重用性问题一般我们是这样的
//querylist封装成类对象
@org.junit.Test
public void querylistBeas() {
String sql = "select *from user1 where id>?";
List<UserBean> sumlistBean = jdbcTemplate.query(sql, new UserBeanRoMapper(), 0);
System.out.println(sumlistBean);
}
private class UserBeanRoMapper implements RowMapper<UserBean>{
public UserBean mapRow(ResultSet resultSet, int i) throws SQLException {
UserBean bean=new UserBean();
bean.setId(resultSet.getInt("id"));
bean.setName(resultSet.getString("name"));
return bean;
}
}
JDBC Template的优缺点:
- JDB Template是Spring框架对JDBC操作的封装,简单、灵活但不过强大
- 实际应用中还需要和其它ORM框架混合使用
- 优点:
- 简单(简化了很多代码)
- 灵活(简单的封装,使用起来跟JDBC API是一样的)
- 缺点:
- SQL与Java代码参杂(对程序用的要求较高)
- 功能不丰富(分页查询…)
持久化的特点
- 必须(数据需要存储…)
- 机械化(规则简单,数据中的字段一一对应的)
ROM
- 对象-关系
Spring事务管理:
概念
- 什么是事务:
- 事务一般特指数据库事务(Database Transaction),是指作为一个程序执行单元执行的一系列操作,要么完全执行,要么完全不执行。
- 事务的特性
- 原子性(atomicity)结构上
- 一个事务是一个不可分割的工作单位
- 一致性(consistency)业务合理性的角度
- 事务必须是使数据库从一个一致性状态变到另一个一致性状态
- 隔离性(isolatiion)
- 一个事务的执行不能被其他事务干扰。(集群并发,上锁什么的)
- 持久性(durability)
- 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
- 原子性(atomicity)结构上
Mysql事务处理
一、基本规则:
- MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务。
- show engines; -- 查看服务器支持的引擎
- default-storage-engine =Innodb -- my.ini修改默认引擎
- MySQL默认以自动提交(autocommit)模式运行
- 语句
- BEGIN(STARTTRANSACTION)
- 显式地开启一个事务
- COMMIT
- 提交事务,并使已对数据库进行的所有修改变为永久性的
- ROLLBACK
- 回滚事务,并撤退正在进行的所有未提交的修改。
二、事务并发问题:
- 脏读(解决方法:让用户只能读取永久性的数据)
- 不可重复读(解决方法:给事务加锁(锁行))
- 幻读(解决方法:也是加锁,只不过是锁表)
- BEGIN(STARTTRANSACTION)
注意:问题解决的同时,工作效率会越来越低
- 语句:
- select @@tx_isolation;
- 查询默认隔离级别(默认是可重复读)
- set session transaction isolation level XXX
- 设置当前会话隔离级别
- select @@tx_isolation;
JDBC事务处理
- Connection接口
- JDBC的事务处理是基于Connection的,JDBC通过Connection对象进行事务管理
- JDBC默认事务处理行为是自动提交。
- 事务相关方法
- setAutoCommit
- 设置自动提交
- commit
- 提交事务
- rollback
- 回滚事务
- setAutoCommit
- JDBC事务隔离级别:
- 隔离级别
- TRANSACTION_NONE(不支持事务)
- TRANSACTION_READ_UNCCMMITED
- TRANSACTION_READ_COMMITTED
- TRANSACTION_REPEATABLE_READ
- TRANSACTION_SERIALIZABLE
- 事务隔离级别设置
- getTransactionIsolation
- 获取当前隔离级别
- setTransactionIsoIation
- 设置隔离级别
- getTransactionIsolation
- 隔离级别
Spring事务处理API
TransationDefinition接口
- 隔离级别:
- ISOLATION_DEFAULT(使用数据默认)
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIABLE
- 默认超时
- TIMEOUT_DEFAULT
- 默认30秒
- TIMEOUT_DEFAULT
- Spring事务传播行为:
- PROPAGATION_REQUIRED(默认的,用的最多的)
- 支撑当前事务,如果当前没有事务,就新建一个事务
- PROPAGATION_SUPPORTS
- 支持当前事务,如果当前没有事务就以非事务方式执行
- PROPAGATION_MANDATORY
- 支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW
- 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED
- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER
- 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED
- 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,就新建一个事务。
- PROPAGATION_REQUIRED(默认的,用的最多的)
Spring 编程式事务处理
基于底层API的编程式事务管理:
- PlatformTransactionManager
- TransactionDefintion
- TransactionStatus
基于TransactionTemplate 的编程式事务管理
- TransactionTemplate
一、基于底层API的编程式事务管理:
实现类:
@Component
public class OrderServiceIm implements OrderService {
@Autowired
private OrderIm orderDao;
@Autowired
private ProderIm proderDao;
@Autowired
private PlatformTransactionManager transactionManager;//事务管理器对象
@Autowired
private TransactionDefinition transactionDefinition;//事务定义
public void add(Order order) {
// order.setConfirmDate();
order.setState("待付款");
TransactionStatus tstate = transactionManager.getTransaction(transactionDefinition);
try {
orderDao.insert(order);
Goods goods=proderDao.selcet(Integer.parseInt(order.getGid()));
goods.setInventorynum(goods.getInventorynum()-order.getNum());
proderDao.update(goods);
transactionManager.commit(tstate);
}catch (Exception e){
e.printStackTrace();
transactionManager.rollback(tstate);
}
}
}
Spring配置文件:
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
<!--设置行为等级-->
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
</beans>
二、基于TransactionTemplate 的编程式事务管理
实现类:
@Component
public class OrderServiceIm implements OrderService {
@Autowired
private OrderIm orderDao;
@Autowired
private ProderIm proderDao;
@Autowired
private PlatformTransactionManager transactionManager;//事务管理器对象
@Autowired
private TransactionTemplate transactionTemplate;//事务模版
public void add(final Order order) {
order.setState("待付款");
transactionTemplate.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus transactionStatus) {
try {
orderDao.insert(order);
Goods goods=proderDao.selcet(Integer.parseInt(order.getGid()));
goods.setInventorynum(goods.getInventorynum()-order.getNum());
proderDao.update(goods);
}catch (Exception e){
e.printStackTrace();
transactionStatus.setRollbackOnly();//回滚
}
return null;
}
});
}
}
Spring配置:
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc"/>
<!--创建管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--创建管理模板-->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<!--指定管理器-->
<property name="transactionManager" ref="transactionManager"/>
</bean>
</beans>
Spring 声明式事务处理
概述:
- Spring的声明式事务处理是建立在AOP的基础之上的。其本质是对方法前后进行拦截,然后再目标方法开始之前创建或者加入一个事务,再执行完目标方法之后根据执行情况提交或者回滚事务。
- 建议再开发中使用声明式事务,是因为这样可以是的业务代码纯粹干净,方便后期的代码维护。
处理方式(第三种和第四种最常用):
- 基于TransactionInterceptor的声明式事务处理
- 基于TransactionProxyFactoryBean的声明式事务处理
- 基于命名空间的声明式事务管理
- 基于@Transactional的声明式事务管理
一、TransactionInterceptor:
实现类:
@Component(value = "OrderServiceIm1")
public class OrderServiceIm implements OrderService {
@Autowired
private OrderIm orderDao;
@Autowired
private ProderIm proderDao;
public void add(final Order order) {
order.setState("待付款");
orderDao.insert(order);
Goods goods=proderDao.selcet(Integer.parseInt(order.getGid()));
goods.setInventorynum(goods.getInventorynum()-order.getNum());
proderDao.update(goods);
}
}
Spring配置文件:
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc"/>
<!--创建管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--拦截的对象(增强的目标)-->
<bean id="OrderServiceImTarget" class="com.test.ioc.Bean.Service.impl.OrderServiceIm"/>
<!--配置拦截器-->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<!--事务管机器-->
<property name="transactionManager" ref="transactionManager"/>
<!--事务的属性-->
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="set**">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="**">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!--生成代理-->
<bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目标-->
<property name="target" ref="OrderServiceImTarget"/>
<!--拦截器-->
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
</list>
</property>
</bean>
</beans>
二、TransactionProxyFactoryBean
- 就是用一个bean配置实现代理和拦截器,该有的东西还是要用,只是从结构上看紧凑一些。
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc"/>
<!--创建管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--拦截的对象(增强的目标)-->
<bean id="OrderServiceImTarget" class="com.test.ioc.Bean.Service.impl.OrderServiceIm"/>
<bean id="orderService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--事务管机器-->
<property name="transactionManager" ref="transactionManager"/>
<!--事务的属性-->
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="set**">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="**">PROPAGATION_REQUIRED</prop>
</props>
</property>
<!--目标-->
<property name="target" ref="OrderServiceImTarget"/>
</bean>
</beans>
三、命名空间的声明式事务管理
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc"/>
<!--创建管理器-->
<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="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!--切入点-->
<aop:pointcut id="pointCut" expression="execution(* com.test.ioc.Bean.Service.impl.OrderServiceIm.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointCut"/>
</aop:config>
</beans>
四、@Transactional的声明式事务管理
Spring配置:
<?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">
<import resource="spring.xml"/>
<context:component-scan base-package="com.test.ioc.Bean.Service.impl6"/>
<!--创建管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
实现类:
@Component
public class OrderServiceIm implements OrderService {
private OrderIm orderDao=new OrderIm();
private ProderIm proderDao=new ProderIm();
@Transactional(propagation = Propagation.REQUIRED)
public void add(final Order order) {
order.setState("待付款");
orderDao.insert(order);
Goods goods=proderDao.selcet(Integer.parseInt(order.getGid()));
goods.setInventorynum(goods.getInventorynum()-order.getNum());
proderDao.update(goods);
}
}
开发需要注意的:
关于配置与注解
- 配置
- 非Java代码
- 便于后期维护
- 注解
- 灵活、精简
- 应用场合
- 一处配置与多处注解
- 代码精简
- 注解需要复杂的非Java代码