spring aop 配置 原

  • spring aop

       面向切面编程(AOP),是软件编程思想发展到一定阶段的产物,是对面向对象编程(OOP)的有益补充。AOP一般适用于具有横切逻辑的场合,如访问控制、事务管理、性能监测等。
        面向切面编程,简单的说,就是在不改变源程序的基础上为代码段增加新的功能,对代码进行增强处理,它的设计思想来源于代理设计模式。

了解之后需要知道以下概念:

        1.增强类型:
                前置增强(通知),在在原方法执行之前进行处理,同理还有后置增强、环绕增强、异常抛出增强、最终增强等。
        2.连接点(Joinpoint):
                程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。
        3.切点(Pointcut):
                每个类都拥有多个连接点:类的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

需求:UserDao 接口(根据id 获取用户信息)

/**
 * @note 用户Dao
 * @author liuh
 * */
public interface UserDao {

	/**
	 * @note 根据用户id 获取用户
	 * @author liuh
	 * */
	public User getUser(int id);
}

UserDaoImpl 实现

/**
 * @note 用户UserDao 接口实现
 * @author liuh
 * */
public class UserDaoImpl implements UserDao{

	/**
	 * @note 根据id 获取用户
	 * @author liuh
	 * */
	@Override
	public User getUser(int id){
		System.out.println("模拟根据【id】获取用户信息实现");
		User u=new User();
		u.setId(id);
		u.setName("hello");
		return u;
	}

}
  • 基于xml配置实现spring aop增强

1.前置增强

(1)创建UserLogger类,新增before_log方法:

/**
 * @note 用户增强类
 * @author liuh
 * */
public class UserLogger {

	/**
	 * @note 前置
	 * */
	public void before_log(JoinPoint jp){
		System.out.println("调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs());
	}
}

(2)配置增强实现

	<!-- 用户Dao 实现Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用户增强 实现 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增强 -->
		<aop:aspect ref="use_log">
			<!-- 前置增强 -->
			<aop:before method="before_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

2.后置增强

(1)在新增UserLogger类 afterReturn_log方法

	/**
	 * @note 后置返回值
	 * */
	public void afterReturn_log(JoinPoint jp,Object obj){
		System.out.println("调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs()+"返回值:"+((User)obj).getName());
	}

(2)后置增强配置

    <!-- 用户Dao 实现Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用户增强 实现 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增强 -->
		<aop:aspect ref="use_log">
			<!-- 后置增强 返回值 -->
			<aop:after-returning method="afterReturn_log" pointcut-ref="useDao_point" returning="obj"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

3.环绕增强

(1)在新增UserLogger类 round_log方法

	/**
	 * @note 环绕
	 * */
	public void round_log(ProceedingJoinPoint jp){
		System.out.println("前置调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs());
		Object obj=null;
		try {
			obj =jp.proceed();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("后置调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs()+"返回值:"+((User)obj).getId());
	}

(2)环绕配置

    <!-- 用户Dao 实现Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用户增强 实现 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增强 -->
		<aop:aspect ref="use_log">
			<!-- 环绕 -->
			<aop:around method="round_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

4.异常增强(异常抛出增强方法)

(1)在新增UserLogger类 catch_log方法

	/**
	 * @note 异常增强
	 * */
	public void catch_log(JoinPoint jp,RuntimeException e){
		try {
			throw e;
		} catch (Exception e2) {
			System.out.println("处理该异常");
			// TODO: handle exception
		}
		System.out.println("异常调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs()+"异常:"+e.getMessage());
	}

(2)异常增强配置

    <!-- 用户Dao 实现Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用户增强 实现 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增强 -->
		<aop:aspect ref="use_log">
			<!-- 异常增强 -->
			<aop:after-throwing method="catch_log" pointcut-ref="useDao_point" throwing="e"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->

5.最终增强

        我们知道,如果在目标方法中抛出了异常,就不会执行后续的后置增强。在AspectJ中为我们提供了一种最终增强,无论是否出了异常都会执行,类似于try-catch中的finally块,一般用于释放资源

(1)在新增UserLogger类 after_log方法

	/**
	 * @note 最终
	 * */
	public void after_log(JoinPoint jp){
		System.out.println("最终增强调用"+jp.getTarget()+"的方法:"+jp.getSignature().getName()+"参数:"+jp.getArgs());
	}

(2)最终增强配置

    <!-- 用户Dao 实现Bean -->
	<bean id="aop_userImpl" class="com.liuh.aop.UserDaoImpl"></bean>
	<!-- 用户增强 实现 Bean -->
	<bean id="use_log" class="com.liuh.aop.UserLogger"></bean>
	<!-- aop stat -->
	<aop:config>
		<!-- 切点 -->
		<aop:pointcut expression="execution(public * getUser(..))" id="useDao_point"/>
		<!-- 增强 -->
		<aop:aspect ref="use_log">
			<!-- 最终增强 -->
			<aop:after method="after_log" pointcut-ref="useDao_point"/>
		</aop:aspect>
	</aop:config>
	<!-- aop end -->
  • 测试
public class AopTest {

	public static void main(String[] args) {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userD=(UserDao)ctx.getBean("aop_userImpl");
		userD.getUser(1123);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章