Java学习框架之spring37天(--AOP 注解使用-- 事物tx的注解使用;)

第一步: 在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;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值