SpringAOP面向切面编程

Posted Orlion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringAOP面向切面编程相关的知识,希望对你有一定的参考价值。

原文链接:http://www.orlion.ga/205/

一、AOP简介

1、AOP概念

    参考文章:http://www.orlion.ml/57

2、AOP的产生

    对于如下方法:

    public class UserDAOImpl implements UserDAO{
    
    	public void saveUser(User user){
    		doSaveUser();
    	}
    }

    想在saveUser方法中执行保存用户之前和之后记录当前时间以求出saveUser花费了多少时间,方法有很多种,最直观的写法就是在doSaveUser()前后加代码取出当前时间:

    public class UserDAOImpl implements UserDAO{
    
    	public void saveUser(User user){
    		int beginTime = getCurrentTime();
    		
    		doSaveUser();
    		
    		int endTime = getCurrentTime();
    	}
    }

    还有一种方法就是重新写一个类继承自UserDAOImpl然后重写saveUser方法,如下:

    public class UserDAOImpl2 extends UserDAOImpl{
        @Override
	public void saveUser(User user){
		int beginTime = getCurrentTime();
		
		super.saveUser();
		
		int endTime = getCurrentTime();
	}
    }

    这种方法耦合性太强,一旦父类改变了子类也会改变,慎用继承

    再有一种方法就是在调用saveUser()方法时加代码:

    

    public class UserService{
        
	public void saveUser(User user){
	        UserDAOImpl userDao = new UserDAOImpl();
		int beginTime = getCurrentTime();
		
		userDao.saveUser();
		
		int endTime = getCurrentTime();
	}
    }

    

    现在如果让我们将项目中所有的对数据库进行CRUD操作的方法都加上获取时间的代码,显然工作量太大,这时候就用动态代理: (可参考http://www.orlion.ml/207/)

    UserDAOImpl.java

    package ml.orlion.dao.impl;
    
    import ml.orlion.dao.UserDAO;
    import ml.orlion.model.User;
    
    public class UserDAOImpl implements UserDAO{
    
    	public void saveUser(User user){
    		System.out.println("save usering");
    	}
    }

    TimeInterceptor.java

    package ml.orlion.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class TimeInterceptor implements InvocationHandler{
    	
    	private Object target;// 被代理的对象
    	
    	public Object getTarget() {
    		return target;
    	}
    	public void setTarget(Object target) {
    		this.target = target;
    	}
    	public void beforeMethod(Method m){
    		System.out.println(m.getName() + "begin start");
    	}
    	@Override
    	public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
    		
    		this.beforeMethod(m);// 插入方法
    		m.invoke(target, args);
    		return null;
    	}
    }

    测试

    public static void testProxy(){
	// 首先产生一个被代理对象
	UserDAO userDao = new UserDAOImpl();
	// 下一步将被代理对象交给InvocationHandler即TimeInterceptor
	TimeInterceptor ti = new TimeInterceptor();
	// 设置被代理对象
	ti.setTarget(userDao);
	// 根据被代理对象产生一个代理
	UserDAO userProxy = (UserDAO)Proxy.newProxyInstance(UserDAO.class.getClassLoader(), new Class[]{UserDAO.class}, ti);
	userProxy.saveUser(new User());
    }

    运行可以看到控制台打印:saveUserbegin start      save usering

二、使用Spring AOP

UserDAO.java:

package ml.orlion.dao;

import ml.orlion.model.User;

public interface UserDAO {
	public void saveUser(User user);
}

UserDAOImpl.java:

package ml.orlion.dao.impl;

import ml.orlion.dao.UserDAO;
import ml.orlion.model.User;

public class UserDAOImpl implements UserDAO{

	public void saveUser(User user){
		System.out.println("save usering");
	}
}

UserService.java

package ml.orlion.service;

import ml.orlion.dao.UserDAO;
import ml.orlion.dao.impl.UserDAOImpl;
import ml.orlion.model.User;

public class UserService {

	private UserDAO userDAO = new UserDAOImpl();

	public UserDAO getUserDao() {
		
		return userDAO;
	}

	public void setUserDao(UserDAO userDAO) {
		this.userDAO = userDAO;
	}
	
	public void saveUser(User user){
		this.userDAO.saveUser(user);
	}
}

LogInterceptor.java

package ml.orlion.aop;

public class LogInterceptor {

	public void before(){
		System.out.println("before");
	}
}

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.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	<bean id="logInterceptor" class="ml.orlion.aop.LogInterceptor">
	</bean>
  	<bean id="userDao" class="ml.orlion.dao.impl.UserDAOImpl">
 	
  	</bean>
  	<bean id="userService" class="ml.orlion.service.UserService">
  		<property name="userDao" ref="userDao"/>
  	</bean>
  	<aop:config>
  		<aop:pointcut expression="execution(public * ml.orlion.service..*.add(..))"
  			id="servicePointcut" />
  		<aop:aspect id="logAspect" ref="logInterceptor">
  			<aop:before method="before" pointcut-ref="servicePointcut"/>
  		</aop:aspect>
  	</aop:config>
</beans>

测试:

BeanFactory appContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) appContext.getBean("userService");
userService.saveUser(new User());

 

以上是关于SpringAOP面向切面编程的主要内容,如果未能解决你的问题,请参考以下文章

Spring——面向切面编程(AOP模块)

图文并茂!!!一文搞懂SpringAOP(面向切面编程)

图文并茂!!!一文搞懂SpringAOP(面向切面编程)

SpringAOPAOP面向切面编程

java web013——Spring AOP面向切面编程

Spring AOP 简介