代理模式 为什么要学习代理模式?
因为这就是SpringAOP的底层
我们的业务逻辑是这样的
dao层——>service层——>controller层——>前端
动态代理和静态代理一样,动态代理是动态生成的。
在了解动态代理之前先了解两个类
Proxy:代理类,它里面有个方法很重要newProxyInstance()
InvokationHandler:接口它里面有个抽象方法 就是对方法进行增强的具体操作
AOP:在不改变项目源码的情况下,实现对某一方法的改动 就是AOP面向切面编程,AOP的底层使用的是动态代理
动态代理操作
首先,确定要操作的接口方法 与接口实现类
接口`
public interface Show {
void gethost();
}
接口实现类
public class Host implements Show{
@Override
public void gethost() {
System.out.println("房子出租");
}
}
动态代理类
package com.mumu.dao01;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Proxy1 implements InvocationHandler{
public static void main(String[] args) {
/** 将接口传递过来 newProxyInstance要用 */
Class[] interfaces={Show.class};
/** 用 Proxy类 调用 newProxyInstance方法 参数1;当前所在类的加载器, 参数2;需要切入的接口 参数3;代理类的对象 */
Show o = (Show)Proxy.newProxyInstance(Proxy1.class.getClassLoader(), interfaces, new Proxy1(new Host()));
o.gethost(); //调用接口的方法
}
//将接口的实现类传递过来
Object obj;
//用构造器的方式传递过来
public Proxy1(Object obj){
this.obj=obj;
}
/** 这个接口的实现类方法就是对增强接口方法的 具体操作 */
@Override //参数1;接口实现类的对象 参数2;代理的方法 参数3;数组
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("12");
Object invoke = method.invoke(obj, args);// 这个调用就是调用接口中 原始的方法 在它上面或下面 都可以写代码 增强方法
System.out.println("45");
return invoke;
}
}
了解完动态代理
我们来了解AOP操作术语
连接点:类里面哪些地方可以被增强,这些方法就叫连接点
切入点:实际真正增强的方法,成为切入点
通知(增强):实际增强的逻辑部分称为通知
切面:是动作
AOP操作准备:
1 spring框架一般都是基于AspectJ实现AOP操作
什么是AspectJ?
AspevcJ是独立的框架,它不是spring的组成部分,一般把AspevcJ一起使用,进行AOP操作
首先了解切入点表达式:
表示要对com.mumu.test.Userimp.add()方法进行切面操作
execution(* com.mumu.test.Userimp.add(..))
它配合注解使用
例如
//声明在哪个方法切入 @Before 是在前置切入
@Before(value = "execution(* com.mumu.test.Userimp.add(..))")
需要增强方法
package com.mumu.edu.test;
import org.springframework.stereotype.Component;
@Component
public class Userimp {
public void myince() {
System.out.println("我是userimp");
}
}
代理类
@Component
@Aspect//加上这个注解 表示这是个切面声明
public class Porxy02 {
//声明在哪个方法切入 @Before 是在前置切入
@Before(value = "execution(* com.mumu.test.Userimp.add(..))")
public void before(){
System.out.println("前置");
}
}
配置文件
<?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.mumu.test"> </context:component-scan>
<!-- 开启aop-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
测试类
package com.mumu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Userimp userAop = context.getBean("userimp", Userimp.class);
userAop.add();
}
}
注意点 我们在使用AspectJ时 要导包
完成操作后
那么 问题来了,如果有多个方法 都想对某一个方法进行增强操作
如何判定优先级?
只需要在增强类上面添加注解@Order(数值型值) 数字值越小 优先级越高