代理:通过代理对象访问目标对象,这样可以在目标对象实现的基础上,增强额外的功能操作(即扩展目标对象的功能)。
简言之,在调用目标对象的方法前后做一些操作,以达到增强的目的。
注意:类内部自调用不会触发AOP。
注解代理实现:
注解类:
package com.xxx.annotations;
import java.lang.annotation.*;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface User {
}
AOP:
package com.xxx.aspects;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
public class AuthorityAspect {
@Around("@annotation(user)")
private <T> T user(ProceedingJoinPoint joinPoint, User user) throws Throwable {
/**
* 方法执行前相关操作
**/
T proceed = (T) joinPoint.proceed();
/**
* 方法执行后相关操作
**/
return proceed;
}
}
静态代理、动态代理、cglib代理、多切面顺序控制:
动物类接口:
public interface Animal {
void call();
}
小狗类
public class Dog implements Animal {
@Override
public void call() {
System.out.println("汪汪");
}
}
小猫类
public class Cat implements Animal {
@Override
public void call() {
System.out.println("喵喵");
}
}
静态代理
动物代理类
public class AnimalProxy implements Animal {
private Animal animal;
public AnimalProxy(Animal animal){
this.animal=animal;
}
@Override
public void call() {
System.out.println("就像");
animal.call();
System.out.println("一只"+this.animal.getClass().getSimpleName()+"一样");
}
}
测试类:
public class TestProxy {
//静态代理
@Test
public void testStaticProxy(){
Dog dog=new Dog();
AnimalProxy animalProxy=new AnimalProxy(dog);
animalProxy.call();
}
}
动态代理
动态动物代理类
public class DynamicAnimalProxy implements InvocationHandler {
private Animal animal;
public DynamicAnimalProxy(Animal animal){
this.animal=animal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("就像");
method.invoke(animal,args);
System.out.println("一样");
return null;
}
}
测试类
public class TestProxy {
//静态代理
@Test
public void testStaticProxy() {
Dog dog = new Dog();
AnimalProxy animalProxy = new AnimalProxy(dog);
animalProxy.call();
}
@Test
public void testDynamicProxy() {
Cat cat = new Cat();
DynamicAnimalProxy dynamicAnimalProxy = new DynamicAnimalProxy(cat);
ClassLoader classLoader = cat.getClass().getClassLoader();
Animal animal = (Animal) Proxy.newProxyInstance(classLoader, cat.getClass().getInterfaces(), dynamicAnimalProxy);
animal.call();
}
}
cglib代理
注解方式:
@RestController
public class DogController {
@Resource
private Animal dog;
@RequestMapping(value = "/dogCall",method = RequestMethod.GET)
public JsonData dogCall(String name){
dog.call();
return JsonData.success();
}
}
@Aspect
@Component("myAspect")
public class MyAspect {
// * 表示任意返回类型 (..) 表示匹配任意参数
@Pointcut("execution(* com.sunshine.shine.Service.impl.Dog.call(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("before------");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("around before------");
joinPoint.proceed(); //执行被加强的方法
System.out.println("around after------");
}
@After("pointCut()")
public void after(){
System.out.println("after-------");
}
@AfterReturning("pointCut()")
public void afterReturning(){
System.out.println("afterReturn-----");
}
@AfterThrowing("pointCut()")
public void afterThrowing(){
System.out.println("afterThrowing----");
}
}
运行程序,请求 /dogCall,结果如下
around before------
before------
汪汪
around after------
after-------
afterReturn-----
XML配置文件方式:
<bean id="aspectXml" class="com.sunshine.shine.Proxys.MyAspectXml" />
<aop:aspectj-autoproxy proxy-target-class="true" />
<aop:config>
<aop:aspect id="aspect" ref="aspectXml">
<aop:pointcut expression="execution(* com.sunshine.shine.Service.impl.Dog.call(..))" id="refcall" />
<aop:before method="before" pointcut-ref="refcall" />
<aop:after-returning method="afterReturning" pointcut-ref="refcall" />
<aop:after-throwing method="afterThrowing" pointcut-ref="refcall" />
<aop:around method="around" pointcut-ref="refcall" />
<aop:after method="after" pointcut-ref="refcall"/>
</aop:aspect>
</aop:config>
public class MyAspectXml {
public void before(){
System.out.println("before------");
}
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("around before------");
joinPoint.proceed();//执行被加强的方法
System.out.println("around after------");
}
public void after(){
System.out.println("after-------");
}
public void afterReturning(){
System.out.println("afterReturn-----");
}
public void afterThrowing(){
System.out.println("afterThrowing----");
}
}
运行程序,请求 /dogCall,结果如下
before------
around before------
汪汪
after-------
around after------
afterReturn-----
总结:
注解方式执行顺序:
around before
before
执行方法
around after
after
afterReturning
XML文件配置方式执行顺序:
before
around before
执行方法
after
around after
afterReturning
多切面顺序控制
原切面加个顺序 @Order(1)
@Order(1)
@Aspect
@Component("myAspect")
public class MyAspect {
// @DeclareParents(value = "com.sunshine.shine.Service.impl.Dog+",defaultImpl = AnimalServiceImpl.class)
// public AnimalService animalService;
@Pointcut("execution(* com.sunshine.shine.Service.impl.Dog.call(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("before------");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("around before------");
joinPoint.proceed();
System.out.println("around after------");
}
@After("pointCut()")
public void after(){
System.out.println("after-------");
}
@AfterReturning("pointCut()")
public void afterReturning(){
System.out.println("afterReturn-----");
}
@AfterThrowing("pointCut()")
public void afterThrowing(){
System.out.println("afterThrowing----");
}
}
再添加两个相同的切面
@Aspect
@Component
public class MyAspect2 implements Ordered {
// @DeclareParents(value = "com.sunshine.shine.Service.impl.Dog+",defaultImpl = AnimalServiceImpl.class)
// public AnimalService animalService;
@Pointcut("execution(* com.sunshine.shine.Service.impl.Dog.call(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("2before------");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("2around before------");
joinPoint.proceed();
System.out.println("2around after------");
}
@After("pointCut()")
public void after(){
System.out.println("2after-------");
}
@AfterReturning("pointCut()")
public void afterReturning(){
System.out.println("2afterReturn-----");
}
@AfterThrowing("pointCut()")
public void afterThrowing(){
System.out.println("2afterThrowing----");
}
@Override
public int getOrder() {
return -1;
}
}
@Order(0)
@Aspect
@Component
public class MyAspect3 {
// @DeclareParents(value = "com.sunshine.shine.Service.impl.Dog+",defaultImpl = AnimalServiceImpl.class)
// public AnimalService animalService;
@Pointcut("execution(* com.sunshine.shine.Service.impl.Dog.call(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("3before------");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("3around before------");
joinPoint.proceed();
System.out.println("3around after------");
}
@After("pointCut()")
public void after(){
System.out.println("3after-------");
}
@AfterReturning("pointCut()")
public void afterReturning(){
System.out.println("3afterReturn-----");
}
@AfterThrowing("pointCut()")
public void afterThrowing(){
System.out.println("3afterThrowing----");
}
}
运行结果(类似责任链):
2around before------
2before------
3around before------
3before------
around before------
before------
汪汪
around after------
after-------
afterReturn-----
3around after------
3after-------
3afterReturn-----
2around after------
2after-------
2afterReturn-----
运用了两种实现控制顺序方式:
1、@Order
2、implement Ordered
@Override
public int getOrder() {
return -1;
}
MyAspect Order值为 1
MyAspect2 Order值为 -1
MyAspect3 Order值为 0
-1<0<1
所以顺序为 2 -> 3 -> 1