码迷,mamicode.com
首页 > 其他好文 > 详细

(6)AOP编程

时间:2016-07-23 13:45:28      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:spring


1、概念

AOP,aspect object programming  面向切面编程

功能: 让关注点代码与业务代码分离!

关注点

重复代码就叫做关注点

切面

关注点形成的类,就叫切面(类)!

面向切面编程,就是指对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。

切入点

执行目标对象方法,动态植入切面代码。

可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。

 

Spring AOP的4个jar包

a) spring-aop-3.2.5.RELEASE.jar 【位于spring-framework-3.2.5.RELEASE/libs目录内】

b) aopalliance-.jar

aopalliance-.jar  http://www.java2s.com/Code/Jar/a/Downloadaopalliancejar.htm

aopalliance-1.0-sources.jar  http://www.java2s.com/Code/Jar/a/Downloadaopalliance10sourcesjar.htm

c) aspectjrt.jaraspectjweaver.jar(aspectj是优秀的aop组件)

AspectJ 1.8.7   http://www.eclipse.org/aspectj/downloads.php

aspectj-1.8.7.jar   http://www.eclipse.org/downloads/download.php?file=/tools/aspectj/aspectj-1.8.7.jar

aspectj-1.8.7-src.jar   http://www.eclipse.org/downloads/download.php?file=/tools/aspectj/aspectj-1.8.7-src.jar

aspectj-1.8.7.jar和aspectj-1.8.7-src.jar实际是压缩包,可以将后缀名改为".rar",再打开之后,可以看到里面的jar包。


2、用注释(Annotation)方式实现AOP编程

步骤:

1) 先引入aop相关的4个jar文件

2) bean.xml中引入aop名称空间  xmlns:aop

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd"
        default-autowire="byType">
</beans>


3) 开启aop注解

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4) 使用注解

@Aspect 指定一个类为切面类

@Pointcut("execution(* cn.rk.spring.aop_annotation.*.*(..))")  指定切入点表达式

@Before("pointCut_()") 前置通知: 目标方法之前执行

@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)

@AfterReturning("pointCut_()")    返回后通知: 执行方法结束前执行(异常不执行)

@AfterThrowing("pointCut_()") 异常通知:  出现异常时候执行

@Around("pointCut_()") 环绕通知: 环绕目标方法执行


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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd"
        default-autowire="byType">

	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.rk.hibernate.f_aop_annotation"></context:component-scan>
	
	<!-- 开启aop注解方式 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	
</beans>

IUserDao.java

package com.rk.hibernate.f_aop_annotation;

//接口
public interface IUserDao
{
	void save();
}

UserDao.java

package com.rk.hibernate.f_aop_annotation;

import org.springframework.stereotype.Component;

/**
 * 目标对象
 */
@Component // 加入IOC容器
public class UserDao implements IUserDao
{
	@Override
	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
//		int a = 1/0;
	}
}

OrderDao.java

package com.rk.hibernate.f_aop_annotation;

import org.springframework.stereotype.Component;

/**
 * 目标对象 *
 */
@Component
public class OrderDao
{

	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
	}
}

Aop.java

package com.rk.hibernate.f_aop_annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect // 指定当前类为切面类
public class Aop
{
	// 指定切入点表达式: 拦截哪些方法; 即为哪些类生成代理对象
	@Pointcut("execution(* com.rk.hibernate.f_aop_annotation.*.*(..))")
	public void point_cut()
	{
		
	}
	
	// 前置通知 : 在执行目标方法之前执行
	@Before("point_cut()")
	public void before()
	{
		System.out.println("Aop.before()");
	}
	
	// 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】
	@After("point_cut()")
	public void after()
	{
		System.out.println("Aop.after()");
	}
	
	// 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
	@AfterReturning("point_cut()")
	public void afterReturning()
	{
		System.out.println("Aop.afterReturning()");
	}
	
	// 异常通知: 当目标方法执行异常时候执行此关注点代码
	@AfterThrowing("point_cut()")
	public void afterThrowing()
	{
		System.out.println("Aop.afterThrowing()");
	}
	
	// 环绕通知:环绕目标方式执行
	@Around("point_cut()")
	public void around(ProceedingJoinPoint pjp) throws Throwable
	{
		System.out.println("环绕前....");
		pjp.proceed();  // 执行目标方法
		System.out.println("环绕后....");
	}
}

App.java

package com.rk.hibernate.f_aop_annotation;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
	private ApplicationContext ac = new ClassPathXmlApplicationContext("/com/rk/hibernate/f_aop_annotation/applicationContext.xml");
	
	
	@Test
	public void test()
	{
		// 目标对象有实现接口,spring会自动选择“JDK代理”
		IUserDao userDao = (IUserDao) ac.getBean("userDao");
		System.out.println(userDao.getClass());
		userDao.save();
		
		System.out.println();
		System.out.println("----------------------------------------");
		System.out.println();
		
		// 目标对象没有实现接口, spring会用“cglib代理”
		OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
		System.out.println(orderDao.getClass());
		orderDao.save();
	}
}

输出: 

class com.sun.proxy.$Proxy12
环绕前....
Aop.before()
-----核心业务:保存!!!------
环绕后....
Aop.after()
Aop.afterReturning()

----------------------------------------

class com.rk.hibernate.f_aop_annotation.OrderDao$$EnhancerByCGLIB$$9b746598
环绕前....
Aop.before()
-----核心业务:保存!!!------
环绕后....
Aop.after()
Aop.afterReturning()

 

3、用XML方式实现AOP编程

使用XML方式实现aop编程的步骤:

1) 引入jar文件  【aop 相关jar, 4个】

2) 引入aop名称空间 xmls:aop

3)aop 配置

--> 配置切面类 (重复执行代码形成的类)

--> aop配置:拦截哪些方法 / 拦截到方法后应用通知代码


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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd"
        default-autowire="byType">

	<!-- dao 实例 -->
	<bean id="userDao" class="com.rk.hibernate.g_aop_xml.UserDao"></bean>
	<bean id="orderDao" class="com.rk.hibernate.g_aop_xml.OrderDao"></bean>

	<!-- 切面类 -->	
	<bean id="aop" class="com.rk.hibernate.g_aop_xml.Aop"></bean>

	<!-- Aop配置 -->
	<aop:config>
		<!-- 定义一个切入点表达式: 拦截哪些方法 -->
		<aop:pointcut id="pt" expression="execution(* com.rk.hibernate.g_aop_xml.UserDao.*(..))"/>
		<!-- 切面 -->
		<aop:aspect ref="aop">
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pt"/>
			<!-- 前置通知: 在目标方法调用前执行 -->
			<aop:before method="before" pointcut-ref="pt"/>
			<!-- 后置通知: -->
			<aop:after method="after" pointcut-ref="pt"/>
			<!-- 返回后通知 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pt"/>
			<!-- 异常通知 -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
		</aop:aspect>
	</aop:config>
	
</beans>

IUserDao.java

package com.rk.hibernate.g_aop_xml;

//接口
public interface IUserDao
{
	void save();
}

UserDao.java

package com.rk.hibernate.g_aop_xml;

/**
 * 目标对象
 */
public class UserDao implements IUserDao
{
	@Override
	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
//		int a = 1/0;
	}
}

OrderDao.java

package com.rk.hibernate.g_aop_xml;

/**
 * 目标对象 *
 */
public class OrderDao
{

	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
	}
}

Aop.java

package com.rk.hibernate.g_aop_xml;

import org.aspectj.lang.ProceedingJoinPoint;

public class Aop
{
	public void point_cut()
	{
		
	}
	
	public void before()
	{
		System.out.println("Aop.before()");
	}
	
	public void after()
	{
		System.out.println("Aop.after()");
	}
	
	public void afterReturning()
	{
		System.out.println("Aop.afterReturning()");
	}
	
	public void afterThrowing()
	{
		System.out.println("Aop.afterThrowing()");
	}
	
	public void around(ProceedingJoinPoint pjp) throws Throwable
	{
		System.out.println("环绕前....");
		pjp.proceed();  // 执行目标方法
		System.out.println("环绕后....");
	}
}

App.java

package com.rk.hibernate.g_aop_xml;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
	private ApplicationContext ac = new ClassPathXmlApplicationContext("/com/rk/hibernate/g_aop_xml/applicationContext.xml");
	
	
	@Test
	public void test()
	{
		// 目标对象有实现接口,spring会自动选择“JDK代理”
		IUserDao userDao = (IUserDao) ac.getBean("userDao");
		System.out.println(userDao.getClass());
		userDao.save();
		
		System.out.println();
		System.out.println("----------------------------------------");
		System.out.println();
		
		// 目标对象没有实现接口, spring会用“cglib代理”
		OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
		System.out.println(orderDao.getClass());
		orderDao.save();
	}
}

输出: 

class com.sun.proxy.$Proxy4
环绕前....
Aop.before()
-----核心业务:保存!!!------
环绕后....
Aop.after()
Aop.afterReturning()

----------------------------------------

class com.rk.hibernate.g_aop_xml.OrderDao
-----核心业务:保存!!!------

4、切入点表达式

切入点表达式:可以对指定的“方法”进行拦截;  从而给指定的方法所在的类生层代理对象。


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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd"
        default-autowire="byType">

	<!-- dao 实例 -->
	<bean id="userDao" class="com.rk.hibernate.h_aop_pointcut.UserDao"></bean>
	<bean id="orderDao" class="com.rk.hibernate.h_aop_pointcut.OrderDao"></bean>

	<!-- 切面类 -->	
	<bean id="aop" class="com.rk.hibernate.h_aop_pointcut.Aop"></bean>

	<!-- Aop配置 -->
	<aop:config>
		<!-- 【拦截所有public方法】 -->
		<!-- <aop:pointcut id="pt" expression="execution(public * *(..))"/> -->
		
		<!-- 【拦截所有save开头的方法 】 -->
		<!-- <aop:pointcut id="pt" expression="execution(* save*(..))"/> -->
		
		<!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.update(..))"/> -->
		
		<!-- 【拦截指定类的所有方法】 -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.*(..))"/> -->
		
		<!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk..*.*(..))"/> -->
		
		<!-- 【多个表达式】 -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..) ) || execution(* com.rk.hibernate.h_aop_pointcut.OrderDao.save(..))"/> -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..) ) or execution(* com.rk.hibernate.h_aop_pointcut.OrderDao.save(..))"/> -->
		
		<!-- 下面2个且关系的,没有意义 -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..) ) &amp;&amp; execution(* com.rk.hibernate.h_aop_pointcut.OrderDao.save(..))"/> -->
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..) ) and execution(* com.rk.hibernate.h_aop_pointcut.OrderDao.save(..))"/> -->

		<!-- 【取非值】 注意:如果使用not,前面必须要有一个“空格”-->
		<!-- <aop:pointcut id="pt" expression="! execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..))"/> -->
		<aop:pointcut id="pt" expression=" not execution(* com.rk.hibernate.h_aop_pointcut.UserDao.save(..))"/>
		
		<!-- 切面 -->
		<aop:aspect ref="aop">
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pt"/>
		</aop:aspect>
	</aop:config>
	
</beans>

IUserDao.java

package com.rk.hibernate.h_aop_pointcut;

//接口
public interface IUserDao
{
	void save();
	void update();
}

UserDao.java

package com.rk.hibernate.h_aop_pointcut;

/**
 * 目标对象
 */
public class UserDao implements IUserDao
{
	@Override
	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
//		int a = 1/0;
	}

	@Override
	public void update()
	{
		System.out.println("-----核心业务:更新!!!------");
	}
}

OrderDao.java

package com.rk.hibernate.h_aop_pointcut;

/**
 * 目标对象 *
 */
public class OrderDao
{

	public void save()
	{
		System.out.println("-----核心业务:保存!!!------");
	}
}

Aop.java

package com.rk.hibernate.h_aop_pointcut;

import org.aspectj.lang.ProceedingJoinPoint;

public class Aop
{
	public void point_cut()
	{
		
	}
	
	public void around(ProceedingJoinPoint pjp) throws Throwable
	{
		System.out.println("环绕前....");
		pjp.proceed();  // 执行目标方法
		System.out.println("环绕后....");
	}
}

App.java

package com.rk.hibernate.h_aop_pointcut;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
	private ApplicationContext ac = new ClassPathXmlApplicationContext("/com/rk/hibernate/h_aop_pointcut/applicationContext.xml");
	
	
	@Test
	public void test()
	{
		// 目标对象有实现接口,spring会自动选择“JDK代理”
		IUserDao userDao = (IUserDao) ac.getBean("userDao");
		System.out.println(userDao.getClass());
		userDao.save();
		userDao.update();
		
		System.out.println();
		System.out.println("----------------------------------------");
		System.out.println();
		
		// 目标对象没有实现接口, spring会用“cglib代理”
		OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
		System.out.println(orderDao.getClass());
		orderDao.save();
	}
}

 


(6)AOP编程

标签:spring

原文地址:http://lsieun.blog.51cto.com/9210464/1829082

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!