JavaWeb笔记013 SpringAOP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lizhengwei1989/article/details/88599976

技术分析之AOP的相关术语

1. Joinpoint(连接点)	-- 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
2. Pointcut(切入点)		-- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
3. Advice(通知/增强)	-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
4. Introduction(引介)	-- 引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field
5. Target(目标对象)		-- 代理的目标对象
6. Weaving(织入)		-- 是指把增强应用到目标对象来创建新的代理对象的过程
7. Proxy(代理)		-- 一个类被AOP织入增强后,就产生一个结果代理类
8. Aspect(切面)			-- 是切入点和通知的结合,以后咱们自己来编写和配置的
public class UserDaoImpl{
    public void save()
    public void update()
}

1. Joinpoint(连接点)	-- 所有的方法:save、update
2. Pointcut(切入点)		-- 要增强的方法,例如要在save的时候增加保存日志的增强,那么save就是切入点
3. Advice(通知/增强)	-- 具体的增强,例如保存日志
5. Target(目标对象)		-- UserDaoImpl
6. Weaving(织入)		-- 把增强(保存日志)添加到目标,生成代理的过程
7. Proxy(代理)		-- 生成的代理对象
8. Aspect(切面)			-- 切入点和通知 组合成切面:通知需要自己写,切入点需要配置

技术分析之AspectJ的XML方式完成AOP的开发

1. 创建Spring的配置文件,引入具体的AOP的schema约束
	<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.xsd">

2. 创建包结构,编写具体的接口和实现类
	* com.demo2
		* CustomerDao			-- 接口
		* CustomerDaoImpl		-- 实现类

3. 将目标类配置到Spring中
	<bean id="customerDao" class="com.demo2.CustomerDaoImpl"/>

4. 定义切面类
	public class MyAspectXml {
		// 定义通知
		public void log(){
			System.out.println("记录日志...");
		}
	}

5. 在配置文件中定义切面类
	<bean id="myAspectXml" class="com.itheima.demo3.MyAspectXml"/>

6. 在配置文件中完成aop的配置
	<aop:config>
		<!-- 配置切面类:切入点 + 通知(类型) -->
		<aop:aspect ref="myAspectXml">
			<!-- 配置的前置通知,save方法执行之前,增强的方法会执行 -->
			<aop:before method="log" pointcut="execution(public * com.demo3.CustomerDaoImpl.save(..))"/>
		</aop:aspect>
	</aop:config>

7. 完成测试
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath:applicationContext.xml")
	public class Demo3 {
		@Resource(name="customerDao")
		private CustomerDao customerDao;
		@Test
		public void run1(){
			customerDao.save();
			customerDao.update();
			customerDao.delete();
		}
	}

----------

切入点的表达式

1. 再配置切入点的时候,需要定义表达式,重点的格式如下:execution(public * *(..)),具体展开如下:
	* 切入点表达式的格式如下:
		* execution([修饰符] 返回值类型 包名.类名.方法名(参数))
	
	* 修饰符可以省略不写,不是必须要出现的。
	* 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。
	* 包名例如:com.demo3.BookDaoImpl
		* 首先com是不能省略不写的,但是可以使用 * 代替
		* 中间的包名可以使用 * 号代替
		* 如果想省略中间的包名可以使用 .. 
		*   *..*表示所有的包
	
	* 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl表示以DaoImpl结尾的
	* 方法也可以使用 * 号代替,也可以是save*,表示以save开头的
	* 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..
<!--完全匹配的方式-->
<!-- <aop:before method="log" pointcut="execution(public void com.demo3.CustomerDaoImpl.save())"/> -->
<!-- public 可以省略不写 -->
<!-- <aop:before method="log" pointcut="execution(void com.demo3.CustomerDaoImpl.save())"/> -->

<!-- void,返回值可以出现 * 表示任意的返回值,返回值类型不能不写 -->
<!-- <aop:before method="log" pointcut="execution(* com.demo3.CustomerDaoImpl.save())"/> -->

<!-- 包名可以使用 * 代替,不能不写 -->
<!-- <aop:before method="log" pointcut="execution(* com.*.CustomerDaoImpl.save())"/> -->

<!-- 包的简写的方式,任意的包的结构 -->
<!-- <aop:before method="log" pointcut="execution(* *..*.CustomerDaoImpl.save())"/> -->

<!-- 编写类的写法 -->
<!-- <aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save())"/> -->

<!-- 方法编写 -->
<!-- <aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save*())"/> -->




execution(* *..*.*DaoImpl.save*(..))  这个表示:返回值任意,所有包下,以DaoImpl结尾的类中的save开头的,参数为任意   的方法

AOP的通知类型

1. 前置通知
	* 在目标类的方法执行之前执行。
	* 配置文件信息:参考上面
	* 应用:可以对方法的参数来做校验

2. 最终通知
	* 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
	* 在配置文件中编写具体的配置:
	* <aop:after method="after" pointcut="execution(public void com.demo3.CustomerDaoImpl.save())"/>
	* 应用:例如像释放资源

3. 后置通知
	* 方法正常执行后的通知。		
	* 在配置文件中编写具体的配置:
	* <aop:after-returning method="afterReturn" pointcut="execution(public void com.demo3.CustomerDaoImpl.save())"/>
	* 应用:可以修改方法的返回值

4. 异常抛出通知
	* 在抛出异常后通知
	* 在配置文件中编写具体的配置:<aop:after-throwing method="afterThorwing" pointcut-ref="myPointcut3"/>	
	* 应用:包装异常的信息

5. 环绕通知
	* 方法的执行前后执行。
	* 在配置文件中编写具体的配置
	* <aop:around method="around" pointcut="execution(public void com.demo3.CustomerDaoImpl.save())"/>
	    	public void around(ProceedingJoinPoint joinPoint){
        		System.out.println("环绕通知1...");
        		try {
        			// 手动让目标对象的方法去执行
        			joinPoint.proceed();
        		} catch (Throwable e) {
        			e.printStackTrace();
        		}
        		System.out.println("环绕通知2...");
        	}
	* 要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。

技术分析之:Spring框架的AOP技术(注解方式)导入的包和配置文件方式相同

1. 创建Spring的配置文件,引入具体的AOP的schema约束
	<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.xsd">
		
	</beans>

2. 创建包结构,编写具体的接口和实现类
	* com.demo1
		* CustomerDao			-- 接口
		* CustomerDaoImpl		-- 实现类

3. 将目标类配置到Spring中
	<bean id="customerDao" class="com.demo1.CustomerDaoImpl"/>

4. 定义切面类
	* 添加切面和通知的注解
		* @Aspect					-- 定义切面类的注解
		
		* 通知类型(注解的参数是切入点的表达式)
			* @Before				-- 前置通知
		    * @AfterReturing		-- 后置通知
		    * @Around				-- 环绕通知
		    * @After				-- 最终通知
		    * @AfterThrowing		-- 异常抛出通知
	
	* 具体的代码如下
		@Aspect
		public class MyAspectAnno {
			@Before(value="execution(public void com.demo1.CustomerDaoImpl.save())")
			public void log(){
				System.out.println("记录日志...");
			}
		}

5. 步骤六:在配置文件中定义切面类
	<bean id="myAspectAnno" class="com.itheima.demo1.MyAspectAnno"/>

6. 步骤七:在配置文件中开启自动代理
	<aop:aspectj-autoproxy/>

7. 完成测试
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath:applicationContext.xml")
	public class Demo1 {
		
		@Resource(name="customerDao")
		private CustomerDao customerDao;
		
		@Test
		public void run1(){
			customerDao.save();
			customerDao.update();
		}
	}

技术分析之通知类型

1. 通知类型
	* @Before				-- 前置通知
    * @AfterReturing		-- 后置通知
    * @Around				-- 环绕通知(目标对象方法默认不执行的,需要手动执行)
    * @After				-- 最终通知
    * @AfterThrowing		-- 异常抛出通知

2. 配置通用的切入点
	* 使用@Pointcut定义通用的切入点
	
	@Aspect
	public class MyAspectAnno {
		@Before(value="MyAspectAnno.fn()")
		public void log(){
			System.out.println("记录日志...");
		}
		@Pointcut(value="execution(public void com.itheima.demo1.CustomerDaoImpl.save())")
		public void fn(){}
	}
3.before,after,around执行顺序是:around,before,after

猜你喜欢

转载自blog.csdn.net/lizhengwei1989/article/details/88599976