spring之AOP学习简单笔记

Aop概念

面向切面编程  是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

利用AOP可以对业务逻辑的各个部分进行隔离,将那些业务无关,却为业务模块所共同调用的逻辑 封装起来,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

 

 

常见应用场景

事务管理、性能监视、权限控制、安全检查、缓存 、日志

Aop原理的动态代理实现【理解】

【1】JDK 本身的动态代理 Proxy 类; 【2】采用 cglib的enhancer增加类

 

JDK本身动态代理,要求必须提供 对应的接口

Cglib的增强可以不用任何接口

 

 

AOP的入门

导入jar包

spring-aop-4.2.4.RELEASE.jar 

<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-aspectsartifactId>
    <version>4.3.10.RELEASEversion>
dependency>

 

编写目标类 及其对应的接口

  IUserService 和  UserService 

编写切面类

  AspectObj 

Spring容器进行相应配置


<bean id="userService" class="com.hzqf.service.impl.UserService"/>
<bean id="prodcutService" class="com.hzqf.service.impl.UserService"/>

<bean id="aspect" class="com.hzqf.aspect.AspectObj"/>

<aop:config>
    
   
    <aop:aspect ref="aspect">
        
        <aop:pointcut id="pointCut" expression="execution(* com.hzqf.service..*.*(..))"/>
        
        <aop:before method="beforeMethod" pointcut-ref="pointCut" />
        
        <aop:after method="afterMethod" pointcut-ref="pointCut" />
       
        <aop:after-returning method="afterReturningMethod" pointcut-ref="pointCut"/>
        
        <aop:after-throwing method="throwingMethod" pointcut-ref="pointCut" />
        
        <aop:around method="aroundMethod" pointcut-ref="pointCut" />
    aop:aspect>

aop:config>

 

进行测试

//读取配置文件
 ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
 IUserService userService =  (IUserService) ac.getBean("userService");
 //userService.insertUser("风味");
 userService.selectUser();

 

切入点表达式

execution() 

语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)

修饰符,一般省略

public 公共方法

* 任意

返回值,不能省略

void 返回没有值

String 返回值字符串

* 任意

包,[省略]

com.qf.crm 固定包

com.qf.crm.*.service crm包下面子包任意 (例如:com.qf.crm.service)

com.qf.crm.. crm包下面的所有子包(含自己)

com.qf.crm.*.service.. crm包下面任意子包,固定目录service,service目录任意包

类,[省略]

UserServiceImpl 指定类

*Impl 以Impl结尾

User* 以User开头

* 任意

方法名,不能省略

addUser 固定方法

add* 以add开头

*Do 以Do结尾

* 任意

(参数)

() 无参

(int) 一个整型

(int ,int) 两个

(..) 参数任意

throws ,可省略,一般不写。

案例:

execution**(public * com.qf.service.impl.*.*(..))**

 

within:

匹配包或子包中的方法

pointcutexp包里的任意类: within(com.test.spring.aop.pointcutexp.*)

pointcutexp包和所有子包里的任意类:within(com.test.spring.aop.pointcutexp..*)

 

this:

匹配实现接口的代理对象中的方法

用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;

案例:实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:this(com.test.spring.aop.pointcutexp.Intf)

当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型

target:

匹配实现接口的目标对象中的方法

用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配

args:

匹配参数格式符合标准的方法

参数为String类型(运行是决定)的方法: args(String)

bean(id) 

对指定的bean所有的方法

@target:

用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;

@within:

用于匹配所有持有指定注解类型内的方法;

带有@Transactional标注的所有类的任意方法:

@within(org.springframework.transaction.annotation.Transactional)

@target(org.springframework.transaction.annotation.Transactional)

 

@annotation:

用于匹配当前执行方法持有指定注解的方法;

带有@Transactional标注的任意方法:@annotation(org.springframework.transaction.annotation.Transactional) @within和@target针对类的注解,@annotation是针对方法的注解

 

@args:

用于匹配当前执行的方法传入的参数持有指定注解的执行;

参数带有@Transactional标注的方法:@args(org.springframework.transaction.annotation.Transactional)

该注解标注在参数上

 

通知类型

before:前置通知(应用:各种校验、日志)

after:最终通知(应用:清理现场)

afterReturning:后置通知(应用:常规数据处理)

around:环绕通知(应用:十分强大,可以做任何事情)

afterThrowing:抛出异常通知(应用:包装异常信息)

 

基于注解的实现方式

目标类

UserService

切面类

AnnotationAspect

配置文件:

<context:component-scan base-package="com.aspect" />
<aop:aspectj-autoproxy />

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Anno.xml")
public class TestAnno {
    @Autowired
    private IUserService user;
    @Test
    public void testAdvice(){
        user.selectUser();
    }
}

SpringAOP的事务

事务的隔离问题: 脏读 、不可重复读、幻读、可串行化

事务的传播属性:在两个业务之间如何共享事务

spring之AOP学习简单笔记_第1张图片

 

案例 : 相互转账问题

增加相应的事务jar包

 

 


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-jdbcartifactId>
    <version>4.3.10.RELEASEversion>
dependency>

<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <version>5.1.45version>
dependency>


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-txartifactId>
    <version>4.3.10.RELEASEversion>
dependency>

 

配置数据库jdbc 连接

   Jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/mybatis

jdbc.username=root

jdbc.password=admin

配置数据源 dataSources


<context:property-placeholder location="classpath:jdbc.properties" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}" />
bean>

增加spring的jdbc操作


<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
    <property name="dataSource" ref="dataSource" />
bean>

在dao中实现数据库的两个操作:

一个增加账户金额的;另外一个减少账户金额的

配置文件:增加jdbcTemplate的属性注入

<bean id="accountDaoImpl" class="com.hzqf.dao.AccountDaoImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate" />
bean>

 

在service中调用dao的操作。并完成 转账业务

配置文件 : 增加 dao的属性注入

<bean id="accountService" class="com.hzqf.service.impl.AccountService" >
    <property name="accountDao" ref="accountDaoImpl" />
  bean>

 

事务管理配置步骤:

增加事务管理器


<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
bean>

配置业务方法的切面


<aop:config>
    
    <aop:pointcut id="allMethods" expression="execution(* com.hzqf.service..*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethods" />
aop:config>

配置业务管理中的方法及其对应的事务属性


<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        
        
        <tx:method name="transaction" isolation="DEFAULT" propagation="REQUIRED" />
        
        <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" />
        
        <tx:method name="select*" read-only="true"/>
    tx:attributes>
tx:advice>

 

 

采用注解的方式:

增加事务管理器


<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
bean>

增加事务注解支持


 <tx:annotation-driven transaction-manager="txManager" /> 

 

在需要增加事务管理的方法类上加上对应的@Transaction 注解

@Transactional //采用注解的方式进行事务控制
public void transaction(final String firstName, final String secondName, final int account) {
    //第二个人扣款
    userDao.accountOut(secondName,account);
    //int i = 1 /0 ;
    //第一个人收款
    userDao.accountIn(firstName,account);
}

你可能感兴趣的:(简单就完事了,spring,java,aop)