第一步: 在Application.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"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--扫描生成bean的注解 -->
<context:component-scan base-package="com.lan"></context:component-scan>
<!--启动aop注解 添加这个标签以后可以使用注解方式进行aop处理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
第二步:指定切点, 以及通知
package com.lan.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//分两步 , 指定类是切面, 第二步: 变成ioc容器中的bean
@Aspect
@Component
@Repository
@Service
@Controller
public class SecondAOP {
//1.切点
@Pointcut("execution(* com.lan.service.impl.*.*(..))")
public void points() {
}
//2.通知 获取参数;
@Before(value = "points()")
public void befores(JoinPoint joinPoint) {
System.out.println("前置通知");
//通过joinPoint参数可以获取到, 切点方法的参数个数是个数组;
//也可以获取到, 切点方法的方法名;
System.out.println(Arrays.asList(joinPoint.getArgs()));
}
//后置返回通知 ;获取到方法名的返回值. value()公共的, pointcut="";
/*
* 我是注解的后置返回通知
method name:name
result=userService,methood:name
*/
@AfterReturning(value="points()",returning="result")
public void afterReturning(JoinPoint joinPoint , Object result) {
System.out.println("我是注解的后置返回通知");
//获取切点中执行方法的(方法名)name, 和
System.out.println("method name:"+joinPoint.getSignature().getName());
System.out.println("result="+result);
}
}
二: 不使用注解情况下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-4.3.xsd">
<bean id="userService" class="com.lan.service.impl.ServiceImpl">
</bean>
<bean id="firstAop" class="com.lan.aop.FristAOP">
</bean>
<!-- 在config里面设置切面 aspect -->
<aop:config>
<!-- aspect:代表切面; -->
<aop:aspect ref="firstAop" >
<!--前置通知执行的方法 指定你要执行哪个类方法的前置方法;-->
<!-- <aop:before method="before" pointcut-ref="firstpoint"/> -->
<!--后置通知执行的方法 第二种方式写切点的位置-->
<!-- <aop:after method="after" pointcut="execution(* com.lan.service.impl.ServiceImpl.*(..))"/> -->
<!-- 连接点 returning 接收我们的返回值来用; 方法中不能抛出异常 after-returning抛出异常不能有返回值的;-->
<aop:after-returning method="returning" returning="result" pointcut-ref="firstpoint" />
<!--捕获异常. -->
<aop:after-throwing method="throwing" throwing="ex" pointcut-ref="firstpoint"/>
<!-- -->
<!-- <aop:around method="arounds" pointcut-ref="firstpoint"/> -->
<!-- 切点作用: 拦截监控我们的方法的; 筛选出来那些条件是符合我条件的; 第一个* 任意返回值;execute(*com.lanou.Service.implement.*(..))
第二个*所有的方法;
第一个*号,后面要加空格;
-->
<aop:pointcut
expression="execution(* com.lan.service.impl.ServiceImpl.*(..))"
id="firstpoint" />
</aop:aspect>
</aop:config>
</beans>
测试方法以及打印结果;
package com.lanou.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.lan.service.impl.ServiceImpl;
public class TestAopAnno {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext
("application-aopzhujie.xml");
ServiceImpl serviceImpl = (ServiceImpl) ac.getBean("userService");
serviceImpl.name();
}
}
/*
* 前置通知
[]
我是UserService的name方法
我是注解的后置返回通知
method name:name
result=userService,methood:name
*
*/
三: 事物管理者使用注解进行管理方法;
1. 没有使用注解模式application.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 引入数据库配置文件 配合${} -->
<context:property-placeholder location="classpath:db.properties"/>
<!--引入的注解标签. 表名这个包下所有的注解都能用;-->
<context:component-scan base-package="com.lanou"></context:component-scan>
<bean id="dataSouce" 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.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 获取sessionFactory的类所在的包; -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 获取数据源 -->
<property name="dataSource" ref="dataSouce"></property>
<!--hibernate自身的配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- 扫描映射文件 -->
<property name="mappingLocations" value="classpath:com/lanou/entity/*.hbm.xml"></property>
</bean>
<!--
1.创建事物管理对象.将我们的sessionfactory交给他管理
给事物管理者注入了sessionfactory
2.对事物管理者提供一些管理原则;
-->
<bean id="tx" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 给事务管理者提供建议.建议是给事务管理者tx. requird: -->
<tx:advice id="advice" transaction-manager="tx">
<tx:attributes >
<!-- <tx:method name="find*" read-only="true"/> --> <!--查询:选择注意命名规范,便于事物管理;. 开启只读 -->
<tx:method name="select*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--给哪个类哪个方法提建议, 要指定建议的类; userdao下面的类都使用通配符注解进来了; -->
<aop:config>
<aop:pointcut expression="execution(* com.lanou.userdao.*.*(..))" id="txCut"/>
<aop:advisor advice-ref="advice" pointcut-ref="txCut"/>
</aop:config>
</beans>
第二种情况 : 在需要使用注解的情况下; application.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 引入数据库配置文件 配合${} -->
<context:property-placeholder location="classpath:db.properties" />
<!--引入的注解标签. 表名这个包下所有的注解都能用; -->
<context:component-scan base-package="com.lanou"></context:component-scan>
<bean id="dataSouce" 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.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 获取sessionFactory的类所在的包; -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 获取数据源 -->
<property name="dataSource" ref="dataSouce"></property>
<!--hibernate自身的配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- 扫描映射文件 -->
<property name="mappingLocations" value="classpath:com/lanou/entity/*.hbm.xml"></property>
</bean>
<!--
1.创建事物管理对象.将我们的sessionfactory交给他管理 spring管理事物. 必须用getcurrentsession;
给事物管理者注入了sessionfactory
2.对事物管理者提供一些管理原则;
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 事务驱动-->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- aop注解扫描-->
<aop:aspectj-autoproxy/>
</beans>
3 .transaction注解如何使用
package com.lanou.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.lanou.entity.Orders;
import com.lanou.entity.User;
import com.lanou.userdao.OrderDao;
import com.lanou.userdao.UserDao;
@Service(value = "payService")
public class PayService {
@Autowired
private UserDao userDao;
@Autowired
private OrderDao orderDao;
// 如果直接在service层这里加上transaction. 将dao 层的transation都去掉 保证用户和order是同一个事务
//这时就会遵循事务的原子性,同生共死;
//可以按照你想要的结果传入参数;
// @Transactional(readOnly=false)默认是false 在查询时候, 可以更改为true;
public void payInfo() {
}
/*
*1. 同一个业务中使用事物;
* 2. 不同的业务类事务的调用
*/
public void completePay() {
User user = new User();
pay(user);
payInfo();
}
@Transactional(readOnly = false)
/* 第一种:@Transactional(propagation=Propagation.REQUIRED)
* 第二种情况:@Transactional(propagation=Propagation.REQUIRES_NEW) 相当于开启一个小事务;大事物包裹住小事务;
* 虽然我们在service层设置了@Transactional(readOnly = false)
* 然后我们在这个大事务中, 开启一个小事物在dao层开启了一个小事务;
*/
public void pay(User user) {
Orders orders = new Orders();
orders.setOrderNo("987345");
// 我们只需要在service层开启一个事务. 就能保证dao层事务统一性;
//使用一transaction 实现事务的原子性, 同时完成, 才算交易完成;
orderDao.addOrder(orders);
userDao.updateUser(user);
int a =5/0;
}
}