Spring实战学习笔记(第四章:AOP)

package c4_aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/*
 * 1,在软件开发中,散布于应用中多处的功能被称为横切关注点,通常来讲,这些横切关注点从
 * 概念上是与应用的业务逻辑相分离的。但是我们往往会直接嵌入到应用的业务逻辑之中,把这
 * 些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的问题。
 * 
 * 2,我们使用依赖注入(DI)管理和配置对象。DI有助于应用对象之间的解耦,而AOP可以实现横
 * 切关注点与他们所影响的对象之间的解耦。
 * 
 * 3,描述切面的术语有通知(advice),切点(pointcut)和连接点(joinpoint)
 *
 * 4,通知:在AOP术语中,切面的工作定义为通知。通知定义了切面是什么以及何时使用,还解
 * 决了何时执行这个工作的问题
 * 	Spring切面可以应用5中类型的通知:
 * 	前置通知(Before):在目标方法被调用之前调用通知功能
 * 	后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么
 * 	返回通知(After-returning):在目标方法成功执行之后调用通知
 * 	异常通知(After-throwing):在目标方法抛出异常后调用通知
 * 	环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定
 *  义的行为
 * 
 * 5,切点:如果说通知定义了切面的什么和何时的话,name切点就定义了何处
 * 
 * 6,切面:切面是通知和切点的结合。通知和切点共同定义了切面的全部内容--他是什么,在何时
 * 和何处完成其功能
 * 
 * 7,织入:织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织
 * 入目标对象中。在目标对象的生命周期里有多个点可以进行织入:
 * 	编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就
 * 是以这种方式织入切面的
 * 	类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),
 * 它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面。
 * 	运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目
 * 标对象动态的创建一个代理对象。Spring AOP就是以这种方式织入切面的。
 * 
 * 	通知包含了需要用于多个应用对象的横切行为,连接点是程序执行过程中能够应用通知的所
 * 有点,切点定义了通知被应用的具体位置(在哪些连接点)。其中关键的概念是切点定义了哪
 * 些连接点会得到通知。
 * 
 * 8,Spring对AOP的支持
 * 	Spring提供了4中类型的AOP支持:
 * 	基于代理的经典Spring AOP
 * 	纯POJO切面
 * 	@AspectJ注解驱动的切面
 * 	注入式AspectJ切面(使用于Spring各版本)
 * 
 * 	前3种都是Spring AOP的变体,Spring AOP构建在动态代理基础之上,因此,Spring对AOP
 * 的支持局限于方法拦截。
 * 
 * 9,Spring在运行时通知对象
 * 通过在代理类中包裹切面,Spring在运行期把切面织入到Spring管理的bean中。
 * 代理类封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理
 * 拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。
 * 
 * 
 */

@Aspect
public class Audience {

	// execution:在方法执行前触发
	// **:返回任意类型
	// *:方法所属的任意类
	// perform:方法
	// & : and,且
	// !bean('woodstock'):任意id不为woodstock的bean
	@Pointcut(value = "execution(** *.perform(..)) && !bean('woodstock')")
	public void performance() {}
	
	@Before("performance()")
	public void silenceCellPhone() {
		System.out.println("表演之前  silencing cellPhone");
	}
	
	@After("performance()")
	public void afterPerformance() {
		System.out.println("表演之后  after performance");
	}
	
	@AfterThrowing("performance()")
	public void demanRefund() {
		System.out.println("表演异常  demanding a refund");
	}
	
	// 环绕通知
	@Around("performance()")
	public void watchPerformance(ProceedingJoinPoint joinPoint) {
		try {
			System.out.println("around before performance...");
			joinPoint.proceed();
			System.out.println("around after performance...");
		}catch(Throwable t) {
			t.printStackTrace();
		}
	}
}

package c4_aop;

public interface Performance {
	
	void perform();

}

package c4_aop;


public class Singer implements Performance{

	@Override
	public void perform() {
		System.out.println("i am a singer, i am singing a song");	
	}

}

package c4_aop;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = {"c4_aop"})
//启动AspectJ自动代理
@EnableAspectJAutoProxy
public class PerformanceConfig {
	
	@Bean("performance")
	public Performance performance() {
		return new Singer();
	}
	
	@Bean
	public Audience audience() {
		return new Audience();
	}

}

package c4_aop;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= {PerformanceConfig.class})
public class AOPTest {
	
	@Autowired
	private Performance performance;
	
	@Test
	public void testAop() {
		performance.perform();
	}

}

Spring实战学习笔记(第四章:AOP)_第1张图片

XML配置:




	
	
	
	
	
	
	
		
		
			
			
			
			
			
			
			
			
		
	


AOP pointcut传参:如记录某一首歌唱了多少次

package c4_aop;

import java.util.ArrayList;
import java.util.List;

public class Singer implements Performance{
	
	private List songs = new ArrayList<>();

	@Override
	public void perform() {
		System.out.println("i am a singer, i am singing a song ");	
	}
	
	@Override
	public void sing(String name) {
		System.out.println("i am singing : " + name);
	}

	public List getSongs() {
		return songs;
	}

	public void setSongs(List songs) {
		this.songs = songs;
	}
	
}

package c4_aop;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SongCounter {
	
	private Map songCounts = new HashMap<>();
	
	@Pointcut("execution(** *.sing(java.lang.String)) && args(songName)")
	public void singerSing(String songName) {}
	
	@Before("singerSing(songName)")
	public void countSong(String songName) {
		songCounts.put(songName, getSongCount(songName) + 1);
	}
	
	public Integer getSongCount(String songName) {
		return songCounts.containsKey(songName) ? songCounts.get(songName) : 0;
	}

}

package c4_aop;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class SongCounterConfig {
	
	@Bean("performance")
	public Performance performance() {
		return new Singer();
	}
	
	@Bean("songCounter")
	public SongCounter songCounter() {
		return new SongCounter();
	}

}

package c4_aop;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= {SongCounterConfig.class})
public class AOPTest {
	
	@Autowired
	private Performance performance;
	
	@Autowired
	private SongCounter songCounter;
	
	@Test
	public void testAspectWithArgs() {
		performance.sing("千里之外");
		performance.sing("听妈妈的话");
		performance.sing("龙战骑士");
		performance.sing("千里之外");
		performance.sing("七里香");
		performance.sing("听妈妈的话");
		performance.sing("菊花台");
		performance.sing("千里之外");
		
		System.out.println("千里之外:" + songCounter.getSongCount("千里之外"));
		System.out.println("听妈妈的话:" + songCounter.getSongCount("听妈妈的话"));
		System.out.println("龙战骑士:" + songCounter.getSongCount("龙战骑士"));
		System.out.println("菊花台:" + songCounter.getSongCount("菊花台"));
		System.out.println("七里香:" + songCounter.getSongCount("七里香"));
	}
	
	/*@Test
	public void testAop() {
		performance.perform();
	}*/

}

Spring实战学习笔记(第四章:AOP)_第2张图片

通过注解为类引入新功能:
为Performance的所有子类添加一个shout方法

package c4_aop;

public interface Performance {
	
	void perform();
	
	void sing(String name);

}

package c4_aop;

import java.util.ArrayList;
import java.util.List;

public class Singer implements Performance{
	
	private List songs = new ArrayList<>();

	@Override
	public void perform() {
		System.out.println("i am a singer, i am singing a song ");	
	}
	
	@Override
	public void sing(String name) {
		System.out.println("i am singing : " + name);
	}

	public List getSongs() {
		return songs;
	}

	public void setSongs(List songs) {
		this.songs = songs;
	}
	
}

package c4_aop;

public interface Animal {
	
	void shout();

}

package c4_aop;

public class Dog implements Animal{

	@Override
	public void shout() {
		System.out.println("wang wang wang...");
		
	}

}

package c4_aop;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class ExtendFuctionConfig {
	
	@Bean
	public Performance performance() {
		return new Singer();
	}
	
	@Bean
	public ExtendFuction extendFuction() {
		return new ExtendFuction();
	}
	
	@Bean
	public Animal animal() {
		return new Dog();
	}

}

package c4_aop;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= {ExtendFuctionConfig.class})
public class ExtendFunctionTest {
	
	@Autowired
	private Performance performance;
	
	@Test
	public void test() {
		Animal animal = (Animal)performance;
		animal.shout();
	}
	
}

Spring实战学习笔记(第四章:AOP)_第3张图片

你可能感兴趣的:(Spring实战学习笔记(第四章:AOP))