AOP简介
aop作用及优势
作用: 在程序运行期间, 在不修改源码的情况下对方法功能进行增强
(白话): 动态的增强代码功能.
优势: 减少重复代码, 提高开发效率, 并且便于维护
(白话): 好用了
aop底层实现
AOP的低层是通过Spring提供的动态代理技术实现的。
Spring通过动态代理技术动态的生成代理对象, 代理方法执行时进行增强功能的介入, 去调用目标对象的方法, 完成功能增强。
基于JDK的动态代理 (如下)
目标方法接口
public interface TargetInterface {
public void save();
}
目标方法实现
public class Target implements TargetInterface {
@Override
public void save() {
System.out.println("save running......");
}
}
增强方法
public class Advice {
public void before(){
System.out.println("前置增强...");
}
public void afterReturning(){
System.out.println("后置增强...");
}
}
测试
public class ProxyTest {
public static void main(String[] args) {
//创建目标对象
Target target = new Target();
//创建增强对象
Advice advice =new Advice();
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.before();
method.invoke(target, args);
advice.afterReturning();
return null;
}
});
proxy.save();
}
}
基于cglib的动态代理
目标方法
public class Target {
public void save() {
System.out.println("save running......");
}
}
增强方法
public class Advice {
public void before(){
System.out.println("前置增强...");
}
public void afterReturning(){
System.out.println("后置增强...");
}
}
测试
public class ProxyTest {
public static void main(String[] args) {
//创建目标对象
Target target = new Target();
//创建增强对象
Advice advice =new Advice();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Target.class);
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, args);
advice.afterReturning();
return invoke;
}
});
Target proxy = (Target) enhancer.create();
proxy.save();
}
}
xml方式实现aop
①导入坐标
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.
②创建目标接口和目标类
目标接口
public interface TargetInterface { public void save();}
目标实现类
public class Target implements TargetInterface { @Override public void save() { System.out.println("save running......"); }}
③创建切面类(增强方法类)
public class MyAspect { public void before(){ System.out.println("前置增强...."); } public void afterReturning(){ System.out.println("后置增强..."); }}
④交给Spring管理
I. 创建applicationcontext.xml
‖. 把对象交给Spring管理
<!--目标对象-->
<bean id="target" class="link.zishu.aop.Target"/><!--切面对象--><bean id="myAspect" class="link.zishu.aop.MyAspect"/>
⑤配置文件中配置织入关系
<!--配置织入, 告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后置增强)-->
<aop:config>
<!--声明切面-->
<aop:aspect ref="myAspect">
<!--切面= 切点 + 通知-->
<!--pointcut="execution(public void link.zishu.aop.Target.save())"/>--> <aop:before method="before" pointcut="execution( * link.zishu.aop.Target.save())"/> <aop:after-returning method="afterReturning" pointcut="execution(* link.zishu.aop.Target.save())"/>
</aop:aspect>
</aop:config>
⑥测试
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void Test1(){
target.save();
}
}
注解方式实现aop
①创建目标接口和目标类
目标接口
public interface TargetInterface { public void save();}
目标实现类
public class Target implements TargetInterface { @Override public void save() { System.out.println("save running......"); }}
②创建切面类(增强方法类)
public class MyAspect { public void before(){ System.out.println("前置增强...."); } public void afterReturning(){ System.out.println("后置增强..."); }}
③交给Spring管理
通过Component注解, 交给Spring管理
④在切面类中使用注解配置织入关系
通过不同的注解, 配置不同增强。 例如: 前置增强 @Before 后置增强 @AfterReturning
@Before("execution(* link.zishu.anno.Target.save())")
public void before(){
System.out.println("前置增强....");
}
⑤在配置文件中开启组件扫描和AOP的自动代理
<!--开启注解扫描 -->
<context:component-scan base-package="link.zishu.anno"/>
<!--aop的自动代理-->
<aop:aspectj-autoproxy />
⑥测试
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext-anno.xml")
public class AnnoTest {
@Autowired
private TargetInterface target;
@Test
public void Test1(){
target.save();
}
}
增强分类
方法名 | 方法名 | 解释 |
---|---|---|
前置通知 | @Before | 调用方法之前通知 |
后置通知 | @After-returning | 调用方法之后通知(方法执行成功时) |
环绕通知 | @Around | 方法调用前后自定义的一些操作 |
异常通知 | @After-throwing | 调用方法之后通知(方法抛出异常时) |
最终通知 | @After | 调用方法之后通知,不管方法执行状态 |