Spring学习笔记(5)---AOP之声明切面

AOP中一些概念

Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.

joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.

Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):代理的目标对象

Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

光看这些定义是很难理解的,所以需要在例子中去消化。

要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间:
<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-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
</beans>


Spring提供了两种切面声明方式,实际工作中我们可以选用其中一种:
基于XML配置方式声明切面。
基于注解方式声明切面。

一,先来基于注解方式声明切面
1.Person类
package com.jzkangta.demo;

public class Person {

	private int userId;
	private String userName;
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

2.代理对象类
package com.jzkangta.demo;

public class PersonService {

	public void save(int userId,String userName){
		System.out.println("save user ----->userId="+userId+",userName="+userName);
	}
	public void delete(int userId){
		System.out.println("delete user ----->userId="+userId);
	}
	public void update(int userId,String userName){
		System.out.println("update user ----->userId="+userId+",userName="+userName);
	}
	public Person find(int userId){
		System.out.println("find user ----->userId="+userId);
		return null;
	}
}


3.切面类
package com.jzkangta.demo;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 这是一个切面类  
 * 切面指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,
 * 类是对物体特征的抽象,而切面横切性关注点的抽象
 * @author Administrator
 *
 */
@Aspect   //切面类需要用该注解标注
public class AspectClass {

	//表达式详解需要查相关资料,这里不多说
	@Pointcut("execution(* com.jzkangta.demo..*.*(..))")  
	/*
	 * 所谓切入点是指我们要对那些joinpoint进行拦截的定义
	 * 声明一个切入点(Pointcut),切入点是一个空的方法来声明的,后面对它的引用就用该方法名	
	 */
	private void myPointcut() {}
	
	/*
	 * 所谓通知是指拦截到joinpoint之后所要做的事情就是通知.
	 * 通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
	 * 定义前置通知,可以传参数,具体请查相关资料
	 * myPointcut()为引用上面定义的切入点
	 */
	@Before("myPointcut()")
	public void doAccessCheck() {
		System.out.println("前置通知执行.......");
	}
	
	//后置通知,异常通知,最终通知,环绕通知,这里就不做演示
}

4.调用main方法
public static void main(String[] args) {
		
		ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
		PersonService personService = (PersonService) ctx.getBean("personService");
		personService.save(1, "jzkangta");
	}


5.beans.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-2.5.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	
	<!-- 启动对@AspectJ注解的支持 -->
	<aop:aspectj-autoproxy/>
	<!-- 注意personService不是一个接口 -->
	<bean id="personService" class="com.jzkangta.demo.PersonService"></bean>
	<!-- 将切面类也交给Spring -->
	<bean id="aspectClass" class="com.jzkangta.demo.AspectClass"></bean>
	
</beans>


运行结果为:
前置通知执行.......
save user ----->userId=1,userName=jzkangta

二,先来基于XML声明切面
1.Person类,2.代理对象类都不用改
2.去掉了注解的切面类
package com.jzkangta.demo2;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 这是一个切面类  
 * 切面指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,
 * 类是对物体特征的抽象,而切面横切性关注点的抽象
 * @author Administrator
 *
 */
public class AspectClass {

	/*
	 * 所谓切入点是指我们要对那些joinpoint进行拦截的定义
	 * 声明一个切入点(Pointcut),切入点是一个空的方法来声明的,后面对它的引用就用该方法名	
	 */
	private void myPointcut() {}
	
	
	public void doAccessCheck() {
		System.out.println("前置通知执行.......");
	}
	
	//后置通知,异常通知,最终通知,环绕通知,这里就不做演示
}

3.beans.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-2.5.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	
	
	<!-- 注意personService不是一个接口 -->
	<bean id="personService" class="com.jzkangta.demo2.PersonService"></bean>
	<!-- 将切面类也交给Spring -->
	<bean id="aspectClass" class="com.jzkangta.demo2.AspectClass"></bean>
	
	<aop:config>
		<aop:aspect id="myaop" ref="aspectClass">
			<aop:pointcut id="mycut"
			expression="execution(*com.jzkangta.demo2..*.*(..))" />
			<!-- method="doAccessCheck"为切面类里的前置通知名 -->
			<aop:before pointcut-ref="mycut" method="doAccessCheck" />
			<!-- 
			<aop:after-returning pointcut-ref="mycut"
				method="后置通知名 " />
			<aop:after-throwing pointcut-ref="mycut"
				method="例外通知名" />
			<aop:after pointcut-ref="mycut" method="最终通知名" />
			<aop:around pointcut-ref="mycut" method="环绕的通知名" />
			 -->
		</aop:aspect>

	</aop:config>
	
</beans>

4.在用main方法执行后,结果如下:
前置通知执行.......
save user ----->userId=1,userName=jzkangta

你可能感兴趣的:(spring,AOP,编程,xml)