Spring Aop实现简单代码实现
/*
* spring的AOP面向切面编程
* 理解:在不改变原来方法的基础上,实现方法增强处理
* 实现方式:
* 1.jdk的Proxy:动态代理,执行的时候处理,要求必须有接口、实现类,代理创建的是实现类的子类。
* 2.cglib:第三方实现的动态代理,要求必须有父类,代理创建的是父类的子类,比jdk实现的要灵活。
* AOP中如果有接口则用jkd动态代理,没有则用cglib
*
* */
jdk实现代码:
代码结构:
1.目标类:Target
2.目标接口类:TargetInterface
3.增强方法类:Advice
4.用Proxy.newProxyInstance实现对目标类的方法增强
public class Target implements TargetInterface { @Override public void save() { System.out.println("save run ..."); } }
public interface TargetInterface { void save(); }
public class Advice { public void before(){ System.out.println("增强前方法。。。。"); } public void after(){ System.out.println("增强后方法"); } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyText { public static void main(String[] args) { Target target=new Target(); Advice advice=new Advice(); TargetInterface proxyInstance = (TargetInterface)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.after(); Object invoke = method.invoke(target, args); advice.after(); return invoke; } }); proxyInstance.save(); } }
cglib实现:
目标类和增强方法一样
import org.springframework.cglib.proxy.*; import java.lang.reflect.Method; /* * spring的AOP面向切面编程 * 理解:在不改变原来方法的基础上,实现方法增强处理 * 实现方式: * 1.jdk的Proxy:动态代理,执行的时候处理,要求必须有接口、实现类,代理创建的是实现类的子类。 * 2.cglib:第三方实现的动态代理,要求必须有父类,代理创建的是父类的子类,比jdk实现的要灵活。 * AOP中如果有接口则用jkd动态代理,没有则用cglib * * cglib步骤: * 1.导入包org.aspectj * 2.代码实现,如下。实现代码和Proxy.newProxyInstance差不多 * */ public class ProxyTest { public static void main(String[] args) { //目标对象 Target target=new Target(); //增强对象 Advice advice=new Advice(); //1.创建增强器 Enhancer enhancer=new Enhancer(); //2.设置父目标 enhancer.setSuperclass(Target.class); //3.设置回调 enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { advice.before(); Object invoke = method.invoke(target, objects); advice.after(); return invoke; } }); //4.创建代理对象 Target proxy = (Target) enhancer.create(); proxy.save(); } }
spring配置方式实现;
包配置:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
xml方式实现:
1.target类
public class Target implements TargetInterface { @Override public void save() { System.out.println("save run ..."); } }
2.接口
public interface TargetInterface { void save(); }
3.切面类
import org.aspectj.lang.ProceedingJoinPoint; /* * aop的重点概念: Pointcut(切入点):被增强的方法 Advice(通知/ 增强):封装增强业务逻辑的方法 Aspect(切面):切点+通知 Weaving(织入):将切点与通知结合的过程 * * * * 前置通知 <aop:before> 用于配置前置通知。指定增强的方法在切入点方法之前执行 后置通知 <aop:after-returning> 用于配置后置通知。指定增强的方法在切入点方法之后执行 环绕通知 <aop:around> 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 异常抛出通知 <aop:throwing> 用于配置异常抛出通知。指定增强的方法在出现异常时执行 最终通知 <aop:after> 用于配置最终通知。无论增强方式执行是否有异常都会执行 * */ public class MyAspect { public void before(){ System.out.println("before增强方法"); } public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("around增强前"); Object proceed = pjp.proceed(); System.out.println("around增强后"); return proceed; } }
4.配置
<?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" xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--目标对象--> <bean id="target" class="cn.web.aop.Target"></bean> <!--切面对象--> <bean id="myAspect" class="cn.web.aop.MyAspect"></bean> <!--配置织入:告诉spring哪些方法需要那总增强--> <aop:config> <!--声明切面--> <aop:aspect ref="myAspect"> <!--切点表达式--> <aop:pointcut id="pointcut" expression="execution( * cn.web.aop.Target.*())"></aop:pointcut> <!--切面:切点+通知--> <!--<aop:before method="before" pointcut="execution(public void cn.web.aop.Target.save())"></aop:before>--> <!--返回值、包、类、方法都可以用通配符取代,表示里面的所有类、方法等--> <aop:before method="before" pointcut="execution( * cn.web.aop.Target.*())"></aop:before> <aop:around method="around" pointcut-ref="pointcut"></aop:around> </aop:aspect> </aop:config> </beans>
5.测试
import cn.web.aop.TargetInterface; 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:applicationContext.xml") public class AopTest { @Autowired private TargetInterface target; @Test public void test(){ target.save(); } }
注解方式实现;
就列些不同的
1.切面类
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /* * aop的重点概念: Pointcut(切入点):被增强的方法 Advice(通知/ 增强):封装增强业务逻辑的方法 Aspect(切面):切点+通知 Weaving(织入):将切点与通知结合的过程 * * * * 前置通知 <aop:before> 用于配置前置通知。指定增强的方法在切入点方法之前执行 后置通知 <aop:after-returning> 用于配置后置通知。指定增强的方法在切入点方法之后执行 环绕通知 <aop:around> 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 异常抛出通知 <aop:throwing> 用于配置异常抛出通知。指定增强的方法在出现异常时执行 最终通知 <aop:after> 用于配置最终通知。无论增强方式执行是否有异常都会执行 * */ @Component @Aspect public class MyAspect { @Before("execution(* cn.web.aop.Target.*(..))") public void before(){ System.out.println("before增强方法"); } @Around("pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("around增强前"); Object proceed = pjp.proceed(); System.out.println("around增强后"); return proceed; } @AfterReturning("pointcut()") public void afterReturning(){ System.out.println("afterReturning返回后"); } //设置切点表达式:可以共用 @Pointcut("execution(* cn.web.aop.Target.*(..))") public void pointcut(){ } }
2.配置
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!--组件扫描--> <context:component-scan base-package="com.itheima.anno"/> <!--aop自动代理--> <aop:aspectj-autoproxy/> </beans>
3.测试
import cn.web.anno.TargetInterface; 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:applicationContext_anno.xml") public class AnnoTest { @Autowired private TargetInterface target; @Test public void test(){ target.save(); } }