ssm:面向切面编程-----使用XML定义切面类

相关实例:
使用特定接口定义切面类
使用注解定义切面类

上述切面类,要么用到了特定接口,要么用到了注解,各有不足之处。使用注解有个问题,就是直接在类里面编写注解,不能分离,不方便修改与维护

其实还有一种方法,既不需要实现特定接口,也不需要使用注解,只需在第三方的配置文件中配置一下,这就是使用XML配置文件定义切面的方式,也是目前最常用的AOP方式。

1.若干AspectJ标签的含义

<aop:config>:配置AOP,实现将一个普通类设置为切面类的功能
<aop:aspect>:配置切面
<aop:pointcut>:配置切点
<aop:before>:配置前置通知,将一个切面方法设置为前置增强
<aop:after-returning>:配置后置通知,将一个切面方法设置为后置通知,有返回值
<aop:around>:配置环绕通知
<aop:after-throwing>:配置异常通知,将一个切面设置为异常抛出增强
<aop:after>:配置最终通知,将一个切面方法设置为后置增强,没有有返回值,无论是否异常都执行

2.定义切点的常用方法(即表达式)

execution(public * *(...)):指定切点为任意公共方法
execution(* save *(...)):指定切点为任何一个以 save 开始的方法
execution(* com.xiaochen.service.*.*(...)):指定切点为定义在service包中的任意类的任意方法
execution(* *.service.*.doUpdate()):指定只有一级包下的service子包下的所有类中的doUpdate()方法为切点
execution(* *..service.*.doUpdate()):指定所有service子包下的所有类中的doUpdate()方法为切点
execution(* com.xiaochen.service.UserService.*(...)):指定切点为UserService类中的任意方法
execution(* com.xiaochen.service.UserService+.*(...)):指定切点:UserSrvice若为接口,则为接口中的及其所有实现类中的任意方法,
														UserSrvice若为类,则为该类及其子类中的任意方法
execution(* doRegister(String,*)):指定切点为:所有doRegister()方法,该方法的第一个参数为String,第二个参数为任意类型。

应用实例:通过XML配置的方式定义一个切面类

项目目录结构图
在这里插入图片描述

IUserDao.java

package com.xiaochen.dao;

public interface IUserDao {
	public void addUser();
}

UserDaoImpl.java

package com.xiaochen.dao;

import org.springframework.stereotype.Component;

//使用注解方式定义一个Bean,其id为userDao
@Component("userDao")
public class UserDaoImpl implements IUserDao{
	@Override
	public void addUser() {
		System.out.println("新增一个用户到数据库中");
		
	}

}

UserService.java

package com.xiaochen.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.xiaochen.dao.IUserDao;

//使用注解方式定义Bean,其id为userService
@Component("userService")
public class UserService {
	//使用注解注入在UserDaoImpl定义好的Bean
	@Resource(name="userDao")
	private IUserDao userDao;	
	//给域属性赋值
	public void setUserDao(IUserDao userDao) {
		this.userDao=userDao;
	}	
	//调用IUserDao的addUser()方法
	public void addUser() {
		userDao.addUser();	
	}
}

Test.java

package com.xiaochen.test;

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

import com.xiaochen.service.UserService;

public class Test {

	public static void main(String[] args) {
		//1.加载配置文件
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//2.从配置文件中获取Bean
		UserService userService=(UserService)context.getBean("userService");
		
		//3.使用Bean
		userService.addUser();

	}

}

MyLog.java

package com.xiaochen.aop;

import com.sun.istack.internal.logging.Logger;

//该类既不实现特定接口,也不加注解
public class MyLog {
	private static final Logger log=Logger.getLogger(MyLog.class);
	public void beforeMethod() {
		log.info("使用XML配置定义切面,开始执行方法。。。");
	}
	public void afterMethod() {
		log.info("使用XML配置定义切面,完成执行方法。。。");
	}
}

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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	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">
        
    <!-- 配置组件扫描器,在指定的基本包中扫描注解 -->
	<context:component-scan base-package="com.xiaochen" />
	
	<!-- 定义切面类 -->
	<!-- 为添加注解的myLog类创建一个Bean -->
	<bean id="myLog" class="com.xiaochen.aop.MyLog" />
	
	<aop:config>
		<!-- 定义切点 -->
		<aop:pointcut expression="execution(* com.xiaochen.service.*.*(..))" id="pointcut" />
		
		<!-- 引用切面类,设置各种通知 -->
		<aop:aspect ref="myLog">
		
			<!-- 将切面类中的beforeMethod方法设置为前置通知 -->
			<aop:before method="beforeMethod" pointcut-ref="pointcut"></aop:before>
			
			<!-- 将切面类中的afterMethod方法设置为后置通知,有返回值 -->
			<aop:after-returning method="afterMethod" pointcut-ref="pointcut"></aop:after-returning>
			
		</aop:aspect>
	</aop:config>
	
	

</beans>

log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.xiaochen=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

运行结果图
在这里插入图片描述


版权声明:本文为weixin_45873215原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。