1.aop原理:动态代理
1.1静态代理:
静态代理是通常说是的23中设计模式代理模式的实现,代理类和被代理类实现同一个接口,在代理类中注入被代理类的对象。实现时调用代理类的方法即可。
首先新建租房接口:
public interface Rent {
void doRent(String houseName);
}
然后新建房东类实现接口:
public class Renter implements Rent{
@Override
public void doRent(String houseName) {
System.out.println("房东租"+houseName);
}
}
新建中介,也实现该接口,此处使用set注入被代理类对象:
public class HouseAgent implements Rent{
private Renter renter;
public Renter getRenter() {
return renter;
}
public void setRenter(Renter renter) {
this.renter = renter;
}
@Override
public void doRent(String houseName) {
this.setRenter(new Renter());
this.getRenter().doRent(houseName);
}
}
测试代码:
public class Test {
public static void main(String[] args) {
HouseAgent houseAgent=new HouseAgent();
houseAgent.doRent("幸福里小区");
}
}
结果:
1.2动态代理
所谓的动态代理在java中实际上就是利用的反射的原理,在运行时动态创建代理类,来代理被代理类的方法(注意,java的动态代理针对的是方法)
java的动态代理涉及到二个重要的类:InvacationHandler和Proxy:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class RentHouseDynamicProxy {
//动态代理,即是在运行时动态创建实现接口的实例(InvocationHandler的实例),同时动态的创建代理该实例的代理实例(Proxy的对象)
public static void main(String[] args) {
InvocationHandler invocationHandler=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//InvocationHandler 调用处理器,是一个接口,此处使用匿名内部类,重写invoke方法,代理接口调用方法时,实际上使用的是invoke方法中的内容
// proxy是Proxy的对象,method是调用的接口的方法,args是接口方法的参数数组
System.out.println(proxy.getClass());//class com.sun.proxy.$Proxy0
System.out.println(method);//public abstract void Structure.proxy.RentHouse.rentHouse(java.lang.String)
System.out.println("房东租"+args[0]);//房东租幸福里小区
return null;
}
};
RentHouse rentHouse= (RentHouse) Proxy.newProxyInstance(RentHouse.class.getClassLoader(), new Class[]{RentHouse.class},invocationHandler);
//使用Proxy类在运行时动态创建接口实例的代理实例,动态载入被代理的类,
// 第一个参数是接口的Class类的类加载器(可不输入),第二个参数是Class类数组,{}中存放接口的class类,第三个参数是InvocationHandler对象,用来处理方法的调用(接口方法的实现)
rentHouse.rentHouse("幸福里小区");
}}
2.aop实现
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.vasen.infra.util.ResponseDataUtil;
@Aspect //切面(类):实际上是代理类
@Component //把切面类纳入spring管理
public class LogAspect {
@Pointcut("execution(public * org.vasen.api.controller.v1.*.*(..))") //切入点,实际上就是被代理类的方法
//切入点,此处为方法的执行,*匹配一个通配符,..匹配多个通配符,+只能用在类名后面,表示类本身和继承类与扩展类
//此处匹配:第一个*是方法返回值,第二*为类,第三个*是方法,..表示多个参数
public void log() {
}
@Before("log()")
public void doBefore(JoinPoint joinPoint){
//joinPoint就是上面的切点的具体方法
System.out.println("程序执行前");
}
@After("log()")
public void doAfter(){
System.out.println("程序执行后");
}
//@Before和@After不会改变原方法的执行
@Around("log()")
public T doAround(ProceedingJoinPoint pjp) throws Throwable {
//ProceedingJoinPoint也是上面的切点的具体方法,在@Around中必须包含此参数
return (T) pjp.proceed();
//使用around可以直接改变方法的执行体和返回值,pjp.proceed()是原方法的执行
}
/* 程序的执行顺序为:
......pjp.proceed()前的代码
@Before中的方法
pjp.proceed();
@After中的方法
.......pjp.proceed()后的代码
*/
}