Spring的AOP

AOP面向切面编程:

	将散落在系统中的公共功能代码进行集中式的管理和配置

	解耦、可扩展性、可维护性的基础上

	切面(要加入的新对象)      切入点(那些方法前或者后添加新功能,方法)    织入(动态代理原理)   连接点(JoinPoint)

不改变原有代码,添加新的代码

动态代理原理
在这里插入图片描述
范例:使用AOP的思想实现用户的添加:

实体类

package com.oupeng.pojo;

public class User {
	private Integer id;
	private String userName;
	private String password;
	private String email;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
    
}

1.编写数据访问层

  • 1.1 数据访问接口
package com.oupeng.dao;

import com.oupeng.pojo.User;

public interface UserDao {
      //定义用户保存的方法
	public int save(User user);
}

  • 1.2 数据访问实现类
package com.oupeng.dao.impl;

import com.oupeng.dao.UserDao;
import com.oupeng.pojo.User;

public class UserDaoImpl implements UserDao{

	@Override
	public int save(User user) {
		System.out.println("保存用户到数据库成功");
		return 1;
	}
   
}

2.编写业务逻辑层

  • 2.1 业务逻辑层接口
package com.oupeng.service;

import com.oupeng.pojo.User;

public interface UserService {
       //定义添加用户
	public int addNewUser(User user);
}

  • 2.2 业务逻辑层实现类
package com.oupeng.service.impl;

import com.oupeng.dao.UserDao;
import com.oupeng.pojo.User;
import com.oupeng.service.UserService;

public class UserServiceImpl implements UserService {
     //注入数据访问层
	/**
	 * 之前:UserDaoImpl ud=new UserDaoImpl();
	 * ud.save(user);
	 */
	
	//Spring
	UserDao ud;
	
	public UserDao getUd() {
		return ud;
	}

	public void setUd(UserDao ud) {
		this.ud = ud;
	}

	@Override
	public int addNewUser(User user) {
		ud.save(user);
		return 2;
	}

}


3 配置spring配置文件


	<!-- 配置数据访问层bean -->
	<bean id="userdao" class="com.oupeng.dao.impl.UserDaoImpl"/>
	<!-- 配置业务逻辑层bean -->
	<bean id="userService" class="com.oupeng.service.impl.UserServiceImpl">
	<property name="ud" ref="userdao"></property>
	</bean>

4.测试类

package com.oupeng.test;

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

import com.oupeng.pojo.User;
import com.oupeng.printer.Printer;
import com.oupeng.service.UserService;

public class TestPrinter {
    @Test
    public void testPrinter() {
      ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");	
      UserService ud=(UserService) context.getBean("userService");
      User user=new User();
      user.setUserName("曹操");
      user.setPassword("565566");
      user.setEmail("256@163.com");
      user.setId(001);
      ud.addNewUser(user);
    }
}

执行结果

保存用户到数据库成功.....

现在在不改原码的情况下,增加新功能
1、实现日志打印
增加AOP用于处理增强的类(定义方法)

package com.oupeng.logger;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class UserServiceLogger {
       private static final Logger log=Logger.getLogger(UserServiceLogger.class);
       //定义用于前置增强处理的方法  JoinPoint连接点可以调用获取方法的名称参数
       public void beforePrintLogger(JoinPoint jp) {
    	   log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法参数"+Arrays.toString(jp.getArgs()));
       }
     //定义用于后置增强处理的方法
       public void afterReturningPrintLogger(JoinPoint jp,Object result){
   		log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法返回值:"+result);
   	}
}

配置文件

<!-- 配置用于增强处理的Bean组件 -->
	<bean id="userservicelogger"
		class="com.oupeng.logger.UserServiceLogger"></bean>
	<!-- 开始进行AOP配置 -->
	<aop:config>
		<!-- 先配置切入点 -->
		<!-- 运行public int addNewUser(com.oupeng.pojo.User)这个方法时增强处理 -->
		<!-- execution(public * addNewUser(..) -->
		<aop:pointcut
			expression="execution(public int addNewUser(com.oupeng.pojo.User))"
			id="pointcut" />
		<!-- 切面配置 -->
		<aop:aspect ref="userservicelogger">
			<!-- 前置增强 -->
			<aop:before method="beforePrintLogger"
				pointcut-ref="pointcut" />
			<!-- 后置增强 -->
			<aop:after-returning
				method="afterReturningPrintLogger" pointcut-ref="pointcut"
				returning="result" />
		</aop:aspect>
	</aop:config>

测试

package com.oupeng.test;

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

import com.oupeng.pojo.User;
import com.oupeng.service.UserService;

public class TestService {
	 @Test
	    public void testService() {
	      ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");	
	      UserService ud=(UserService) context.getBean("userService");
	      User user=new User();
	      user.setUserName("曹操");
	      user.setPassword("565566");
	      user.setEmail("256@163.com");
	      user.setId(001);
	      ud.addNewUser(user);
	    }
}

执行结果

07-15 01:04:16[INFO]org.springframework.context.support.ClassPathXmlApplicationContext
 -Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@769c9116: startup date [Wed Jul 15 01:04:16 CST 2020]; root of context hierarchy
07-15 01:04:16[INFO]org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 -Loading XML bean definitions from class path resource [applicationContext.xml]
07-15 01:04:16[INFO]org.springframework.beans.factory.support.DefaultListableBeanFactory
 -Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@d44fc21: defining beans [HelloSpring,A4,B5,color,gray,printer,userdao,userService,userservicelogger,org.springframework.aop.config.internalAutoProxyCreator,pointcut,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1]; root of factory hierarchy
07-15 01:04:17[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@3d74bf60的addNewUser方法,方法参数[com.oupeng.pojo.User@27ce24aa]
保存用户到数据库成功.....
07-15 01:04:17[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@3d74bf60的addNewUser方法,方法返回值:2
public * addNewUser(com.oupeng.pojo.User): “*”表示匹配所有类型的返回值。
		public void *(com.oupeng.pojo.User): “*”表示匹配所有方法名。
		public void addNewUser(..): “..”表示匹配所有参数个数和类型。
		* com.service.*.*(..):匹配com.service包下所有类的所有方法。
		* com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法

增强处理:前置增强、后置增强、 异常处理增强 、环绕增强、最终增强

异常处理增强:

当程序发生异常的时候,程序员想介入程序执行,完善程序功能,往往用于程序调试
1.编写异常处理增强类 ErrorLogger

package com.oupeng.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;


public class ErrorLogger {
	private Logger log=Logger.getLogger(ErrorLogger.class);
	//定义增强方法
	public void afterThrowing(JoinPoint jp,RuntimeException e){
		log.error(jp.getSignature().getName()+"方法发生了异常"+e.getMessage());
	}
}

2.配置异常处理增强
先配置增强处理Bean
aop配置
配置切入点
切入面
配置异常处理增强

<!-- 配置异常处理增强Bean -->
	<bean id="errorLogger" class="com.oupeng.aop.ErrorLogger" /> 

	<!-- aop配置 -->
	 <aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* com.oupeng.service.UserService.*(..))"
			id="pointcut1" />

		<!-- 配置切面 -->
		<aop:aspect ref="errorLogger">
			<!-- 异常处理增强 -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1" throwing="e" />
		</aop:aspect>
	</aop:config> 

3.目标方法,手动抛出异常

package com.oupeng.service.impl;

import com.oupeng.dao.UserDao;
import com.oupeng.pojo.User;
import com.oupeng.service.UserService;

public class UserServiceImpl implements UserService {
     //注入数据访问层
	/**
	 * 之前:UserDaoImpl ud=new UserDaoImpl();
	 * ud.save(user);
	 */
	
	//Spring
	UserDao ud;
	String str;
	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	//默认构造方法
	public UserServiceImpl(){
		System.out.println("业务逻辑类的默认构造方法");
	}
	
	//带参数构造方法
	public UserServiceImpl(UserDao _ud,String _str){
		this.ud=_ud;
		this.str=_str;
	}
	
	
	public UserDao getUd() {
		return ud;
	}

	public void setUd(UserDao ud) {
		this.ud = ud;
	}

	public void addNewUser(User user) {
		ud.save(user);
		System.out.println(this.str);
		throw new RuntimeException("对不起,程序发生了运行时异常,请联系管理员...");
	}

	


}

4.编写测试 程序

@Test
		public void testException(){
			ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
			UserService ud=(UserService)context.getBean("userService");
			User user=(User)context.getBean("user");
			ud.addNewUser(user);
		}

执行结果

业务逻辑类的默认构造方法
07-15 20:37:30[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@694abbdc的addNewUser方法,方法参数[com.oupeng.pojo.User@4466af20]
保存用户到数据库成功.....
保存用户到数据库成功....
1
张飞
123456
zhangfei@sanguo.com
哈哈
07-15 20:37:30[ERROR]com.oupeng.aop.ErrorLogger
 -addNewUser方法发生了异常对不起,程序发生了运行时异常,请联系管理员...

环绕增强:

在目标方法执行之前和之后共同完善程序现有的功能,以便增强程序功能或者修复Bug

  1. 编写环绕增强处理类
package com.oupeng.aop;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

public class ArroundLogger {
	private Logger log=Logger.getLogger(ArroundLogger.class);
	//定义环绕增强方法
	public Object arroundLogger(ProceedingJoinPoint jp){
		log.info("调用环绕增强开始了..."+jp.getSignature().getName()+"方法被调用,方法参数:"+Arrays.toString(jp.getArgs()));
		Object object=null;
		try {
			//目标方法执行
			 object=jp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		
		log.info("调用环绕增强结束了..."+jp.getSignature().getName()+"方法被调用,方法返回值:"+object);
		return object;
	}
}

  1. 配置环绕增强处理类Bean组件
    先配置增强处理Bean
    aop配置
    配置切入点
    切入面
    配置环绕增强
<!-- 配置环绕增强Bean -->
	<bean id="arroundBean" class="com.oupeng.aop.ArroundLogger" />

	<!-- aop配置 -->
	 <aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* com.oupeng.service.UserService.*(..))"
			id="pointcut2" />

		<!-- 配置切面 -->
		<aop:aspect ref="arroundBean">
			<!-- 环绕增强 -->
			<aop:around method="arroundLogger" pointcut-ref="pointcut2" />
		</aop:aspect>
	</aop:config>

3.编写测试程序:

@Test
	public void testArroundLogger(){
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService ud=(UserService)context.getBean("userService");
		User user=(User)context.getBean("user");
		ud.addNewUser(user);
	}

执行结果

07-15 21:14:16[INFO]org.springframework.context.support.ClassPathXmlApplicationContext
 -Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@769c9116: startup date [Wed Jul 15 21:14:16 CST 2020]; root of context hierarchy
07-15 21:14:16[INFO]org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 -Loading XML bean definitions from class path resource [applicationContext.xml]
07-15 21:14:16[INFO]org.springframework.beans.factory.support.DefaultListableBeanFactory
 -Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1786dec2: defining beans [userdao,userService,user,testentity,userservicelogger,org.springframework.aop.config.internalAutoProxyCreator,pointcut,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,errorLogger,pointcut1,org.springframework.aop.aspectj.AspectJPointcutAdvisor#2,arroundBean,pointcut2,org.springframework.aop.aspectj.AspectJPointcutAdvisor#3]; root of factory hierarchy
业务逻辑类的默认构造方法
07-15 21:14:16[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@7b9a4292的addNewUser方法,方法参数[com.oupeng.pojo.User@59309333]
07-15 21:14:16[INFO]com.oupeng.aop.ArroundLogger
 -调用环绕增强开始了...addNewUser方法被调用,方法参数:[com.oupeng.pojo.User@59309333]
保存用户到数据库成功.....
保存用户到数据库成功....
1
张飞
123456
zhangfei@sanguo.com
哈哈
07-15 21:14:16[INFO]com.oupeng.aop.ArroundLogger
 -调用环绕增强结束了...addNewUser方法被调用,方法返回值:null
07-15 21:14:16[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@7b9a4292的addNewUser方法,方法返回值:null

最终增强:

确保增强处理时一定要执行的业务代码就可以用最终增强处理增强
1.编写最终增强处理类

package com.oupeng.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;


public class AfterLogger {

	private Logger log=Logger.getLogger(AfterLogger.class);
	
	//定义最终增强方法
	
	public void afterLogger(JoinPoint jp){
		System.out.println("出纳开始准备数据....");
		System.out.println("开始打印每周财务报表........");
		System.out.println("开始打印每月的财务报表.....");
	}
}

2.配置最终增强处理类组件
配置增强处理Bena组件
aop配置
配置切入点
切入面
配置最终增强

<!-- 配置最终增强Bean -->
	 <bean id="finalBean" class="com.oupeng.aop.AfterLogger" />

	<!-- aop配置 -->
	<aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* com.oupeng.service.UserService.*(..))"
			id="pointcut3" />

		<!-- 配置切面 -->
		<aop:aspect ref="finalBean">
			<!-- 最终增强 -->
			<aop:after method="afterLogger" pointcut-ref="pointcut3" />
		</aop:aspect>
	</aop:config>

3.编写测试程序:

 @Test
		public void testArroundLogger(){
			ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
			UserService ud=(UserService)context.getBean("userService");
			User user=(User)context.getBean("user");
			ud.addNewUser(user);
		}

执行结果

开始打印每周财务报表........
开始打印每月的财务报表.....
07-15 21:20:38[INFO]com.oupeng.aop.ArroundLogger
 -调用环绕增强结束了...addNewUser方法被调用,方法返回值:null
07-15 21:20:38[INFO]com.oupeng.logger.UserServiceLogger
 -调用com.oupeng.service.impl.UserServiceImpl@6d763516的addNewUser方法,方法返回值:null
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值