Spring--Aop
spring--Aop
Aop核心术语与概念
- 通知(Advice): 定义通知类型和何时执行通知
Before(前置通知):目标方法调用前的通知;
After(后置通知):目标方法调用完成后的通知;
After-Returning (返回通知):目标方法执行返回后调用;
After-Throwing(异常通知):目标方法抛出异常后调用的通知;
Around(环绕通知):包含方法调用的前后返回以及异常执行的一系列行为。
- 连接点(Join point): 通知执行的时机
- 切点(Pointcut): 在何处执行通知
- 切面(Aspect): 切点+通知
- 引入(Introduction):向现有的内添加新的方法或者属性
- 织入(Weaving): 把切面引用到目标对象并创建新的代理对象的过程
织入时间:
AspectJ---编译期
类加载期 --- classLoader --- AspectJ5
Spring --- 运行时织入
实现方式
1.代理Aop&Spring自动代理模式
package com.spring.study.aop.hunter;
/**
* 定义一个行为
*/
public interface HunterAction {
void findAnimal();
}
package com.spring.study.aop.hunter;
/**
* 目标方法
*/
public class Hunter implements HunterAction {
@Override
public void findAnimal() {
System.out.println("Hunter find animal...");
//throw new RuntimeException("throw aop...");
}
}
package com.spring.study.aop.hunter;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
/**
* 定义通知类型
*/
public class HunterAdvices implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
/**
*
* @param o 返回值
* @param method 代理方法
* @param objects 参数列表
* @param o1 目标方法
* @throws Throwable
*/
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("The hunter caught a rabbit");
}
/**
*
* @param method 代理方法
* @param objects 参数列表
* @param o 目标方法
* @throws Throwable
*/
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("The hunter went to the forest");
}
public void afterThrowing(Method method,Object[] args,Object target,RuntimeException e) throws Throwable{
System.out.println("The hunter lost his way reason is " + e);
}
}
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: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.xsd">
<context:component-scan base-package="com.spring.study.aop.hunter"/>
<bean id="hunter" class="com.spring.study.aop.hunter.Hunter"/>
<bean id="hunterAdvices" class="com.spring.study.aop.hunter.HunterAdvices"/>
<!--创建代理对象-->
<bean id="hunterProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="hunter"/>
<property name="interceptorNames" value="hunterAdvices"/>
<property name="proxyInterfaces" value="com.spring.study.aop.hunter.HunterAction"/>
</bean>
<!--定义切点-->
<bean id="hunterPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*findAnimal"/>
</bean>
<!--定义通知-->
<bean id="hunterAdvice" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="hunterAdvices"/>
<property name="pointcut" ref="hunterPointcut"/>
</bean>
<!-- 自动代理-->
<!-- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>-->
<!-- <bean id="hunterAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">-->
<!-- <property name="advice" ref="hunterAdvices"/>-->
<!-- <property name="patterns" value=".*findAnimal"/>-->
<!-- </bean>-->
</beans>
package com.spring.study.bean.aop.hunter;
import com.spring.study.aop.hunter.HunterAction;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:aop/aop-proxy.xml")
@Slf4j
public class HunterTest {
//非自动代理模式,显式指定为代理类
@Autowired
@Qualifier("hunterProxy")
private HunterAction hunterAction;
@Test
public void testHunterAop(){
hunterAction.findAnimal();
}
}
2.pojo切面
引入Aspect依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>x
例行惯例定义行为和主题
package com.spring.study.aop.pojo;
public interface DoAction {
void action();
}
package com.spring.study.aop.pojo;
public class SomeOne implements DoAction {
@Override
public void action() {
System.out.println("Do someting...");
}
}
package com.spring.study.aop.pojo;
/**
*自定义Pojo切面
*/
public class PojoAspect {
public void before(){
System.out.println("init...");
}
public void afterReturning(){
System.out.println("finish...");
}
}
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: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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.spring.study.aop.pojo"/>
<!--target-->
<bean id="someOne" class="com.spring.study.aop.pojo.SomeOne"/>
<!--aspect-->
<bean id="pojoAspect" class="com.spring.study.aop.pojo.PojoAspect"/>
<!-- aop 切入点切面-->
<aop:config>
<aop:pointcut id="someOnePointcut" expression="execution(* com.spring.study.aop.pojo.DoAction.action(..))"/>
<aop:aspect ref="pojoAspect">
<aop:before method="before" pointcut-ref="someOnePointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="someOnePointcut"/>
</aop:aspect>
</aop:config>
</beans>
package com.spring.study.bean.aop.pojo;
import com.spring.study.aop.pojo.DoAction;
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("classpath:aop/aop-pojo.xml")
public class SomeOneTest {
@Autowired
private DoAction doAction;
@Test
public void testPojoAop(){
doAction.action();
}
}
3.Aspect注解形式(推荐)
package com.spring.study.aop.perform;
public interface Performance {
void perform();
void performOrder(int order);
}
package com.spring.study.aop.perform;
import org.springframework.stereotype.Component;
@Component
public class StartPerform implements Performance {
@Override
public void perform() {
System.out.println("Performing...");
}
@Override
public void performOrder(int order) {
System.out.println("perform order is " + order);
}
}
package com.spring.study.aop.perform;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience {
@Pointcut("execution(* com.spring.study.aop.perform.Performance.perform(..))")
public void pointcut(){}
@Before("pointcut()")
public void silenceCellPhones(){
System.out.println("silence cell phone...");
}
@Before("pointcut()")
public void takeSeat(){
System.out.println("taking seat...");
}
@AfterReturning("pointcut()")
public void applause(){
System.out.println("applause...");
}
@AfterThrowing("pointcut()")
public void demandRefund(){
System.out.println("Demanding a refund...");
}
}
环绕通知
package com.spring.study.aop.perform;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AroundPerform {
@Pointcut("execution(* com.spring.study.aop.perform.Performance.perform(..))")
public void pointcut(){}
@Around("pointcut()")
public void start(ProceedingJoinPoint pjp){
try {
System.out.println("Do something before perform");
pjp.proceed();
System.out.println("After perform...");
} catch (Throwable throwable) {
System.out.println("AfterThrowing...");
}
}
}
带入参的情况
package com.spring.study.aop.perform;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class OderAop {
@Pointcut("execution(* com.spring.study.aop.perform.Performance.performOrder(int)) && args(order)")
private void pointcutWithArg(int order){}
@Before("pointcutWithArg(order)")
public void beforeStart(int order){
System.out.println("perform order " + order);
}
}
配置类
package com.spring.study.aop.perform;
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
@EnableAspectJAutoProxy
public class PerformConfig {
@Bean
public Audience audience(){
return new Audience();
}
@Bean
public OderAop oderAop(){
return new OderAop();
}
}
package com.spring.study.bean.aop.perform;
import com.spring.study.aop.perform.PerformConfig;
import com.spring.study.aop.perform.Performance;
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 = PerformConfig.class)
public class PerformTest {
@Autowired
private Performance performance;
@Test
public void testPerform(){
performance.perform();
}
@Test
public void testArg(){
performance.performOrder(2);
}
}
引入新方法
package com.spring.study.aop.perform;
public interface NewAction {
void action();
}
package com.spring.study.aop.perform;
import org.springframework.stereotype.Component;
@Component
public class NewActionImpl implements NewAction {
@Override
public void action() {
System.out.println("new performance...");
}
}
package com.spring.study.aop.perform;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
@Aspect
public class NewActionIntroducer {
//performance+表示在performance的子类型下引入
@DeclareParents(value = "com.spring.study.aop.perform.Performance+",
defaultImpl = NewActionImpl.class)
public static NewAction newAction;
}
补充配置类与测试类
package com.spring.study.aop.perform;
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
@EnableAspectJAutoProxy
public class PerformConfig {
@Bean
public Audience audience() {
return new Audience();
}
@Bean
public OderAop oderAop() {
return new OderAop();
}
@Bean
public NewActionIntroducer newActionIntroducer() {
return new NewActionIntroducer();
}
}
package com.spring.study.bean.aop.perform;
import com.spring.study.aop.perform.NewAction;
import com.spring.study.aop.perform.PerformConfig;
import com.spring.study.aop.perform.Performance;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PerformConfig.class)
public class PerformTest {
@Autowired
private Performance performance;
@Autowired
@Qualifier("startPerform")
private NewAction newAction;
@Test
public void testPerform(){
performance.perform();
//通过aop引入新方法
newAction.action();
}
@Test
public void testArg(){
performance.performOrder(2);
}
}
4.XML无注解形式
// TODO
注入一个切面
// TODO

浙公网安备 33010602011771号