Spring Aop

1.要明白几个知识点

代理模式

|---动态代理

|--静态代理

2.aop(面向切面编程)是oop(面向对象)的补充。

aop也可以分为静态aop(如aspectj就是静态aop)和动态aop(spring aop用的就是动态aop)

其中,动态aop使用的是JDK动态代理或者cglib代理(两者有什么区别?)

3.为什么需要aop

 

4 aspectj实例

首先要下载aspectj.jar,然后java -jar 运行该jar包,然后配置相关环境变量,然后就可以了

先定义两个业务逻辑类

/*
	业务逻辑类Hello
*/
package com.service;
public class Hello
{
	//业务逻辑方法
	public void foo(){
		System.out.println("执行Hello组件的foo方法");
	}
	public int addUser(String name){
		System.out.println("执行Hello组件的addUser方法,添加用户:"+name);
		return 1;
	}
}
/*
	业务逻辑组件World,每个函数完成不同的业务逻辑功能
*/
package com.service;
public class World
{
	public void bar(){
		System.out.println("执行World组件的bar方法");
	}
}

然后定义一个切面类,一个很特别的类,注意看细节

/*
	切片类,该类相当于一个刀子,可以切入到业务逻辑类中
*/
package com.aspect;
public aspect AuthAspect
{
	//第一个星号表示返回值不限,第二个任意类,第三个任意方法,..表示任意个参数和类型
	before():execution(* com.service.*.*(..) )
	{
		System.out.println("业务逻辑执行之前进行权限检查");
	}
}

然后是测试类

package com.test;
import com.service.*;
public class AspectTest
{
	public static void main(String []args){
		Hello hello=new Hello();
		World world=new World();
		//---
		hello.foo();
		hello.addUser("tom");
		//---
		world.bar();
	}
}

把上面几个类使用ajc -d . xxx.java编译好,ajc是aspectj.jar中的命令,理解为加强版的javac

编译过程中会使用动态代理自动为业务逻辑类增加相应的代码,可以用反编译工具查看编译后的.class文件

然后运行test类 java com.test.AspectTest  会看到如下结果:

>业务逻辑执行之前进行权限检查

>执行Hello组件的foo方法

>业务逻辑执行之前进行权限检查

>执行Hello组件的addUser方法,添加用户:tom

>执行World组件的bar方法

--实在是很神奇

---------------------------------------------------------------------

接下来是spring 的aop,首先要搭建环境

选择构建maven项目,下面是依赖(也是spring的基本依赖)

    <dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aop</artifactId>
		<version>4.2.4.RELEASE</version>
	</dependency>
	<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.2.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.4.RELEASE</version>
		</dependency>
		<!-- 添加spring-tx包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.1.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.1.4.RELEASE</version>
		</dependency>
		<!-- spring 依赖包 -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.5</version>
		</dependency>

spring.xml配置文件,注意scema要添加aop相关的

<?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:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    					http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    					http://www.springframework.org/schema/aop
    					http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    
    <bean id="firstAspect" class="com.aop.aspect.FourAdviceAspect"></bean>
    <bean id="secondAspect" class="com.aop.aspect.SecondAspect"></bean>
    <bean id="userService" class="com.service.UserService"></bean>
    
    <aop:config>
        <aop:aspect id="firstAspect" ref="firstAspect" order="2">
        	<aop:after pointcut="execution(* com.service.*.*(..))" method="release"></aop:after>
        	<aop:before pointcut="execution(* com.service.*.*(..))" method="authority"></aop:before>
        	<aop:after-returning  pointcut="execution(* com.service.*.*(..))" returning="rvt" method="log"></aop:after-returning>
        	<aop:around pointcut="execution(* com.service.*.*(..))" method="processTx"></aop:around>
    	</aop:aspect>
    	
        <aop:aspect id="secondAspect" ref="secondAspect">
            <aop:before pointcut="execution(* com.service.*.*(..)) and args(aa)" method="authority"></aop:before>
        </aop:aspect>
        
    </aop:config>
</beans>

两个切面类

package com.aop.aspect;
/*
 * 另一个切面类
 * 
 * */
public class SecondAspect {
	//before
	public void authority(String aa){
		System.out.println("secondAspect before增强");
		System.out.println("目标方法的参数为"+aa);
	}
}
package com.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/*
 * 一个普通的类,作为切面类
 * 类中的每个方法监听一个切入点
 * */
public class FourAdviceAspect {
	//是around、before、after取决于函数中参数的类型
	//用于around
	public Object processTx(ProceedingJoinPoint jp) throws Throwable{
		System.out.println("around增强,执行目标方法之前,执行一些事务...");
		//获取目标方法的参数
		Object []args=jp.getArgs();
		if(args!=null&&args.length>0&&args[0].getClass()==String.class){
			args[0]="EQ专属参数 "+args[0];
		}
		//执行目标方法,并获取返回值
		Object rvt=jp.proceed(args);
		if(rvt==null){
			rvt="null";
		}
		System.out.println("1)目标方法的返回值是:"+rvt.toString());
		System.out.println("1)执行目标方法之后,执行一些事务...");
		return rvt;
	}
	
	//before ,
	public void authority(JoinPoint jp){
		System.out.println("2)before增强,模拟身份权限验证");
		System.out.println("2)before增强,被植入增强处目标的方法为:"+jp.getSignature().getName());
		System.out.println("2)before增强,目标方法的参数为"+jp.getArgs());
		System.out.println("2)before增强,被植入增强处目标对象为"+jp.getTarget());
	}
	//after returning
	public void log(JoinPoint jp,Object rvt){//rvt为目标方法的返回值
		System.out.println("3)after returning增强处理,获取目标方法返回值"+rvt);
		System.out.println("3)after returning增强处理,模拟日志记录功能");
		System.out.println("3)after returning增强处理,被植入增强处理的目标方法为:"+jp.getSignature().getName());
		System.out.println("3)after returning增强,目标方法的参数为"+jp.getArgs());
		System.out.println("3)after returning增强,被植入增强处目标对象为"+jp.getTarget());
	}
	//after
	public void release(JoinPoint jp){
		System.out.println("4)after增强,模拟释放资源...");
		System.out.println("4)after增强,被植入增强处目标的方法为:"+jp.getSignature().getName());
		System.out.println("4)after增强,目标方法的参数为"+jp.getArgs());
		System.out.println("4)after增强,被植入增强处目标对象为"+jp.getTarget());
		
	}
	
}

一个测试类

package com.eqtest;

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

import com.service.UserService;

public class AopTest {
	public static void main(String[] args) {
		//UserService us=new UserService();
		ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
		UserService us=ctx.getBean("userService",UserService.class);
		us.addUser("tom");
		us.queryUser(522);
	}
}

项目的目录结构如下:

Spring Aop - 勿忘心安 - Blog of Hendy

运行结果:

五月 08, 2016 9:33:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6293068a: startup date [Sun May 08 21:33:48 CST 2016]; root of context hierarchy
五月 08, 2016 9:33:49 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
2)before增强,模拟身份权限验证
2)before增强,被植入增强处目标的方法为:addUser
2)before增强,目标方法的参数为[Ljava.lang.Object;@160ee454
2)before增强,被植入增强处目标对象为com.service.UserService@2bb0521c
around增强,执行目标方法之前,执行一些事务...
secondAspect before增强
目标方法的参数为EQ专属参数 tom
增加新的user
1)目标方法的返回值是:null
1)执行目标方法之后,执行一些事务...
3)after returning增强处理,获取目标方法返回值null
3)after returning增强处理,模拟日志记录功能
3)after returning增强处理,被植入增强处理的目标方法为:addUser
3)after returning增强,目标方法的参数为[Ljava.lang.Object;@160ee454
3)after returning增强,被植入增强处目标对象为com.service.UserService@2bb0521c
4)after增强,模拟释放资源...
4)after增强,被植入增强处目标的方法为:addUser
4)after增强,目标方法的参数为[Ljava.lang.Object;@160ee454
4)after增强,被植入增强处目标对象为com.service.UserService@2bb0521c
2)before增强,模拟身份权限验证
2)before增强,被植入增强处目标的方法为:queryUser
2)before增强,目标方法的参数为[Ljava.lang.Object;@747a1b5b
2)before增强,被植入增强处目标对象为com.service.UserService@2bb0521c
around增强,执行目标方法之前,执行一些事务...
查询用户
1)目标方法的返回值是:0000000
1)执行目标方法之后,执行一些事务...
3)after returning增强处理,获取目标方法返回值0000000
3)after returning增强处理,模拟日志记录功能
3)after returning增强处理,被植入增强处理的目标方法为:queryUser
3)after returning增强,目标方法的参数为[Ljava.lang.Object;@747a1b5b
3)after returning增强,被植入增强处目标对象为com.service.UserService@2bb0521c
4)after增强,模拟释放资源...
4)after增强,被植入增强处目标的方法为:queryUser
4)after增强,目标方法的参数为[Ljava.lang.Object;@747a1b5b
4)after增强,被植入增强处目标对象为com.service.UserService@2bb0521c

 

转载于:https://my.oschina.net/eqshen/blog/758100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值