Spring-AOP

@[toc]

AOP介绍

AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想

面向切面编程的几个核心概念 |概念|说明| |--|--| |IOC/DI| 本质是就是Java反射+XML解析| |AOP|本质上Java动态代理| |切点面|要添加代码的地方称作切点| |切面|切点+通知| |通知(增强)|向切点插入的代码称为通知Advice| |连接点|切点的定义|

AOP的实现

AOP术语

术语说明
切面切面泛指交叉业务逻辑。比如事务处理、日志处理就可以理解为切面。常用的切面有通知与顾问。实际就是对主业务逻辑的一种增强
织入织入是指将切面代码插入到目标对象的过程。
连接点连接点只切面可以织入的位置
切入点切入点指切面可以织入的具体位置
通知(Advice)通知是切面的一种实现,可以完成简单织入功能(织入功能就是在这里完成的)。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
顾问(Advisor)顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。 不仅指定了切入时间点,还可以指定具体的切入点

AOP的实现方式

通知类型说明
前置通知(MethodBeforeAdvice目标执行之前调用
后置通知(AfterReturningAdvice)目标方法执行之后调用
环绕通知(MethodInterceptor)目标方法执行之前和执行之后都会调用,且有增强效果
异常处理通知(ThrowsAdvice)目标方法出现异常时调用
基于Schema-based方式实现

导入两个jar包 在这里插入图片描述

前置通知

①创建目标接口和实现类

package com.sxt.service;

public interface UserService {
public void say(String msg);
	
	public String doSome(String msg);
}

public class UserServiceImpl implements UserService {

	@Override
	public void say(String msg) {
		System.out.println("ps"+msg);
		
	}

	@Override
	public String doSome(String msg) {
		System.out.println("doSome"+msg);
		return "英俊";
	}
	
}

②创建前置切面类

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object arg2) throws Throwable {
		System.out.println("前置通知执行了....+"+args[0]+" "+method.getName());
	}

}

③配置文件中配置

<?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: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-4.3.xsd">
 	
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userService"/>
 		<!-- 配置代理类 -->
		<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
			<!-- 设值注入的方式设值 -->
			<property name="target" ref="userService"/>
			<!-- 配置接口 -->
			<property name="interfaces" value="com.sxt.service.UserService"/>
			<!-- 配置通知类型 -->
			<property name="interceptorNames">
			  	<list>
			  		<!-- 配置前置通知 -->
			  		 <value>methodBeforeAdvice</value> 
			  	</list>
			</property>
		</bean>
</beans>

④测试

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService bean = ac.getBean("proxyFactoryBean",UserService.class);
		
		System.out.println(bean.doSome("shuai"));
		System.out.println("--------------------");
		bean.say("sss");
	}
}

在这里插入图片描述

后置通知

①创建目标对象接口和实现类

package com.sxt.service;

public interface UserService {
public void say(String msg);
	
	public String doSome(String msg);
}

public class UserServiceImpl implements UserService {

	@Override
	public void say(String msg) {
		System.out.println("ps"+msg);
		
	}

	@Override
	public String doSome(String msg) {
		System.out.println("doSome"+msg);
		return "英俊";
	}
	
}

②创建切面类

public class MyAfterRunningAdvice implements AfterReturningAdvice {
	/**
	 * @param returnValue 目标方法返回值
	 * @param method 目标方法
	 * @param args 目标方法参数
	 * @param target 目标对象
	 */
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("后置通知执行了...."+returnValue);
	}

}

③配置文件中配置

<?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: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-4.3.xsd">
 	
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userService"/>
 		<!-- 配置代理类 -->
		<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
			<!-- 设值注入的方式设值 -->
			<property name="target" ref="userService"/>
			<!-- 配置接口 -->
			<property name="interfaces" value="com.sxt.service.UserService"/>
			<!-- 配置通知类型 -->
			<property name="interceptorNames">
			  	<list>
			  		<!-- 配置后置通知 -->
			  		<value>myAfterRunningAdvice</value>
			  	</list>
			</property>
		</bean>
</beans>

④测试

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService bean = ac.getBean("proxyFactoryBean",UserService.class);
		
		System.out.println(bean.doSome("shuai"));
		System.out.println("--------------------");
		bean.say("sss");
	}
}

在这里插入图片描述

环绕通知

一、创建目标接口和实现类


```java
package com.sxt.service;

public interface UserService {
public void say(String msg);
	
	public String doSome(String msg);
}

public class UserServiceImpl implements UserService {

	[@Override](https://my.oschina.net/u/1162528)
	public void say(String msg) {
		System.out.println("ps"+msg);
		
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String doSome(String msg) {
		System.out.println("doSome"+msg);
		return "英俊";
	}
	
}

二、创建切面类

/**
 * 环绕通知(切面类)
 * [@author](https://my.oschina.net/arthor) Administrator
 *
 */
public class MyMethodInterceptor implements MethodInterceptor {

	[@Override](https://my.oschina.net/u/1162528)
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("环绕通知前...");
		Object res=invocation.proceed();
		if (res!=null) {
			//增强返回结果
			res=res.toString().toUpperCase();
		}
		System.out.println("环绕通知后...");
		return null;
	}

}

三、配置文件中配置

<?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: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-4.3.xsd">
 	
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userService"/>
 		<!-- 配置代理类 -->
		<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
			<!-- 设值注入的方式设值 -->
			<property name="target" ref="userService"/>
			<!-- 配置接口 -->
			<property name="interfaces" value="com.sxt.service.UserService"/>
			<!-- 配置通知类型 -->
			<property name="interceptorNames">
			  	<list>
			  		<!-- 配置环绕通知 -->
			  		<value>methodInterceptor</value>
			  	</list>
			</property>
		</bean>
</beans>

测试

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService bean = ac.getBean("proxyFactoryBean",UserService.class);
		
		System.out.println(bean.doSome("shuai"));
		System.out.println("--------------------");
		bean.say("sss");
	}
}

在这里插入图片描述

异常通知类

①创建目标对象接口和实现类

package com.sxt.service;

public interface UserService {
public void say(String msg);
	
	public String doSome(String msg);
}

public class UserServiceImpl implements UserService {

	[@Override](https://my.oschina.net/u/1162528)
	public void say(String msg) {
		System.out.println("ps"+msg+1/0);
		
	}

	@Override
	public String doSome(String msg) {
		System.out.println("doSome"+msg);
		return "英俊";
	}
	
}

二、创建切面类

public class MyThrowsAdvice implements ThrowsAdvice {
	public void afterThrowing(Exception ex){
		System.out.println("异常发生了..."+ex.getMessage());
	}
}

三、配置文件中配置

<?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: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-4.3.xsd">
 	
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userService"/>
 		<!-- 配置代理类 -->
		<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
			<!-- 设值注入的方式设值 -->
			<property name="target" ref="userService"/>
			<!-- 配置接口 -->
			<property name="interfaces" value="com.sxt.service.UserService"/>
			<!-- 配置通知类型 -->
			<property name="interceptorNames">
			  	<list>
			  		<!-- 配置环绕通知 -->
			  		<value>methodInterceptor</value>
			  	</list>
			</property>
		</bean>
</beans>

测试

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService bean = ac.getBean("proxyFactoryBean",UserService.class);
		
		System.out.println(bean.doSome("shuai"));
		System.out.println("--------------------");
		bean.say("sss");
	}
}

在这里插入图片描述

基于aspectJ方式实现

aspectJ中的通知类型 |通知类型|说明| |--|--| |前置通知(MethodBeforeAdvice|目标执行之前调用 |后置通知(AfterReturningAdvice)|目标方法执行之后调用| |环绕通知(MethodInterceptor)|目标方法执行之前和执行之后都会调用,且有增强效果| |异常处理通知(ThrowsAdvice)|目标方法出现异常时调用 |最终通知|无论程序执行是否正常,该通知都会执行。类似于try…catch中finally代码块| AspectJ的切入点表达式 在这里插入图片描述 加[ ]表示可以省略 |符号|意义| |--|--| |*|0到多个字符 |..|方法参数中表示任意多个参数,用在包名后表示当前包及其子包路径| |+|用在类名后表示当前类及子类,用在接口后表示接口及实现类|

execution(public * *(. .))
指定切入点为:任意公共方法。
execution(* set *(. .))
指定切入点为:任何一个以“set”开始的方法。
execution(* com.xyz.service.*.*(. .))
指定切入点为:定义在service包里的任意类的任意方法。
execution(* com.xyz.service. .*.*(. .))
指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时,
后面必须跟“*”,表示包、子包下的所有类。
execution(* *.service.*.*(. .))
指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点
execution(* *. .service.*.*(. .))
指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点

AspectJ对于AOP的实现有两种方式 导入jar包 在这里插入图片描述

注解方式

前置通知 创建目标接口和实现类

public interface UserService {
      public void say(String msg);
	
	 public String doSome(String msg);
}

public class UserServiceImpl implements UserService {

	@Override
	public void say(String msg) {
		System.out.println("ps:"+msg);
		
	}

	@Override
	public String doSome(String msg) {
		System.out.println("doSome:"+msg);
		return "英俊";
	}
	

创建切面类

@Aspect

public class MyAspect {
	
	@Before(value="execution(* com.sxt.service.*.*(..))")
	public void beforeMethod(){
		System.out.println("前置通知.......");
	}
}

配置文件中配置

<?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:context="http://www.springframework.org/schema/context"
	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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
 		<!-- <context:component-scan base-package="com.sxt.*"/> -->
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userServiceImpl"/>
 		
 		<!-- 注册切面类 -->
 		<bean class="com.sxt.service.adicve.MyAspect" id="myAspect"/>
 		<!-- 注册自动代理  -->
 		<aop:aspectj-autoproxy/>
</beans>

测试 在这里插入图片描述 后置通知 切面类

@Aspect
public class MyAspect {
	
	/**
	 * 后置通知
	 */
	@AfterReturning(value="execution(* com.sxt.service.*.*(..))")
	public void afterReturing(){
		System.out.println("后置通知.......");
	}
}

在这里插入图片描述 环绕和异常通知和前面的差不多。。。。。最终异常的通知是@After

XML方式

接口和实现类还是用上个案例的 切面类

public class MyAspect {
	
	
	public void beforeMethod(){
		System.out.println("前置通知.......");
	}
}

配置文件中配置

<?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:context="http://www.springframework.org/schema/context"
	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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
 		<!-- <context:component-scan base-package="com.sxt.*"/> -->
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userServiceImpl"/>
 		
 		<!-- 注册切面类 -->
 		<bean class="com.sxt.service.adicve.MyAspect" id="myAspect"/>
 		
 		<aop:config>
 			<!-- 配置切入点 -->
 			<aop:pointcut expression="execution(* *..service.*.*(..))" id="pointcut"/>
 			<!-- 配置切面类 -->
	 			<aop:aspect ref="myAspect">
	 				<!-- 前置通知 -->
 				  	<aop:before method="beforeMethod"  pointcut-ref="pointcut"/>
	 			</aop:aspect>
	 				
 		</aop:config>
</beans>

测试 在这里插入图片描述 各种通知 切面类

package com.sxt.service.adicve;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
	
	
	public void beforeMethod(){
		//System.out.println("前置通知.......");
	}
	/**
	 * 后置通知
	 */
	
	public void afterReturing(){
		System.out.println("后置通知.......");
	}
	/**
	 * 环绕通知
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
	/*
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("环绕通知前....");
		Object res=pjp.proceed();
		System.out.println("环绕通知后....");
		return null;
		
	}*/
	
	public void throwsMethod(){
		//System.out.println("异常发生了.....");
	}
	
	
	public void after(){
		//System.out.println("最终通知");
	}
}

配置文件

<?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:context="http://www.springframework.org/schema/context"
	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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
 		<!-- <context:component-scan base-package="com.sxt.*"/> -->
 		<!-- 配置目标对象 -->
 		<bean class="com.sxt.service.impl.UserServiceImpl" id="userServiceImpl"/>
 		
 		<!-- 注册切面类 -->
 		<bean class="com.sxt.service.adicve.MyAspect" id="myAspect"/>
 		
 		<aop:config>
 			<!-- 配置切入点 -->
 			<aop:pointcut expression="execution(* *..service.*.*(..))" id="pointcut"/>
 			<!-- 配置切面类 -->
	 			<aop:aspect ref="myAspect">
	 				<!-- 前置通知 -->
 				  	<!-- <aop:before method="beforeMethod"  pointcut-ref="pointcut"/> -->
	 				<!-- 后置通知 -->
	 				<!-- <aop:after-returning method="afterReturing" pointcut-ref="pointcut"/> -->
	 				<!-- 环绕通知 -->
	 				<!-- <aop:around method="around" pointcut-ref="pointcut"/> -->
	 				<!-- 异常通知 -->
	 				<!-- <aop:after-throwing method="throwsMethod" pointcut-ref="pointcut"/> -->
	 				<!-- 最终通知 -->
	 				<aop:after method="after" pointcut-ref="pointcut"/>
	 			</aop:aspect>
	 				
 		</aop:config>
</beans>

转载于:https://my.oschina.net/u/4116634/blog/3038909

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值