ssm:spring面向切面编程-----AOP编程初试身手

1.传统编程模式的弊端
通过以下案例你将会发现,虽然在调用addUser()方法时实现了日志的输出,但这个程序有一个问题,
就是不得不在addUser()方法的主业务代码前面添加"log.info(“开始添加用户。。。”)语句,
以及在主业务代码后面添加"log.info("完成添加用户。。。)"语句。
这些语句以硬编码的方式混入主业务代码中,难以分割,可移植性差。

解决问题的思路是将这些日志之类的功能独立出来,作为独立的一个或多个类,在需要时调用,
而且最好不是显示调用,因为如果时显示调用,仍然要在目标方法前面或后面嵌入代码,改进效果有限,最好能自动调用。
这种设想就是一种面向切面编程(AOP)的思想。

应用实例:创建一个分层架构项目,在添加用户的同时输出日志。

项目目录结构图
ssm:spring面向切面编程-----AOP编程初试身手_第1张图片

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.sun.istack.internal.logging.Logger;
import com.xiaochen.dao.IUserDao;

//使用注解方式定义Bean,其id为userService
@Component("userService")
public class UserService {
	//使用注解注入在UserDaoImpl定义好的Bean
	@Resource(name="userDao")
	private IUserDao userDao;
	//用于实现在addUser操作时记录日志
	private static final Logger log=Logger.getLogger(UserService.class);
	
	//给域属性赋值
	public void setUserDao(IUserDao userDao) {
		this.userDao=userDao;
	}
	
	//调用IUserDao的addUser()方法
	public void addUser() {
		log.info("使用传统方式测试开始添加用户。。。");
		userDao.addUser();
		log.info("使用传统方式测试完成添加用户。。。");
	}
}

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();

	}

}

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

applicationContext.xm


 
        
	
	
	

运行结果图
ssm:spring面向切面编程-----AOP编程初试身手_第2张图片

2.AOP的一些基本概念
a.切面:
一个单独的类,通常在此类种定义一些辅助功能或系统功能的方法。

b.切点:
主业务类的有些方法只想专注于完成核心业务逻辑,不想混入一些辅助性的功能,
可以把这些方法定义为切点,切点就是确定什么位置放置切面。

c.通知:
切点确定了使用切面的位置,但什么时候应用切面就由通知来确定。

d.织入:
切面和切点都是独立的功能类,通过织入才能让切面切入切点,
所以织入就是一种配置过程,让切面能准确的切入指定的位置。

应用实例:通过面向切面编程方法改造上面这个项目。
项目目录结构图
ssm:spring面向切面编程-----AOP编程初试身手_第3张图片

关键代码


	
	
	
	
	
		
		
			
	
		
		
		

需要修改的地方与主要步骤
1.删除日志相关代码
2.新建包aop用于定义两个类作为切面(一个类实现前置通知接口,一个类实现后置通知接口)
3.在spring配置文件中引入aop命名空间,依次完成:定义切面,定义切点,通知切点

改动的代码只有1处(即删除UserService中addUser()方法前后的两句日志相关代码),其他代码同上一个传统项目

applicationContext.xml


	
        
    
	
	
	
	
	
	
	
	
		
		
			
	
		
		
		


LoggerBefore.java

package com.xiaochen.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

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

//实现前置通知接口,意味着将来这个方法会作用到目标的开始位置
public class LoggerBefore implements MethodBeforeAdvice{
	private static final Logger log=Logger.getLogger(LoggerBefore.class);
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		log.info("aop方式,开始添加学生。。。");
	}
	
}

LoggerAfter.java

package com.xiaochen.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

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

public class LoggerAfter implements AfterReturningAdvice{
	private static final Logger log=Logger.getLogger(LoggerAfter.class);
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		log.info("aop方式,完成添加学生。。。");
	}

}

运行结果图
ssm:spring面向切面编程-----AOP编程初试身手_第4张图片

你可能感兴趣的:(ssm,aop,spring,log4j)