SpringAOP
AOP表示面向切面编程,它是面向对象编程(OOP)的一种补充
在传统编程当中,需要进行事务处理,日志记录等操作,oop可以通过继承等方式来达到代码重用
AOP采用横向抽取机制,将分散在各个地方的重复代码提取出来,然后再程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。
AOP术语:
Aspect(切面):在实际应用中,切面通常是指封装的用于横向插入系统功能的类
Joinpoint(连接点):在程序执行过程中的某个阶段点,他实际上是对象的一个 操作,例如方法的调用和异常抛出
Pointcut(切入点):是指切面与程序流程的交叉点,切入点指类或者方法名
Advice(通知/增强):AOP框架在特定的切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码。
TargetObject(目标对象):是指所有被通知的对象,也称为被增强对象
Proxy(代理):将通知应用到目标对象之后,被动态创建的对象
Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程
JDK动态代理:
JDK动态代理是通过java.lang.reflect.Proxy类来实现的,可以调用Proxy类的newProxyInstance()方法来创建代理对象
实现步骤:
编写接口
编写实现类
编写切入类
// 切面类
public class MyAspect {
// 以下方法称为增强方法
public void method1() {
System.out.println("检查账号是否正确");
}
public void method2() {
System.out.println("通过检查...");
}
}
编写代理类
public class jdkProxy implements InvocationHandler {
// 声明目标接口
private UserDao userDao;
// 创建代理方法
public Object createProxy(UserDao userDao){
this.userDao = userDao;
// 1、类加载器
ClassLoader classLoader = jdkProxy.class.getClassLoader();
// 2、被代理对象实现的所有接口
Class[] claqq = userDao.getClass().getInterfaces();
// 3、使用代理类,进行增强,返回的事代理后的对象
return Proxy.newProxyInstance(classLoader, claqq, this);
}
/*
*
* 所有动态代理类的方法调用,都会交由invoke()方法处理
* proxy表示被代理后的对象
* method将要被执行的方法信息(通过反射处理)
* args执行方法是需要的参数
*
*
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
// 声明切面
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.method1();
// 在目标类上调用方法,并传入参数
Object obj = method.invoke(userDao, args);
// 后增强
myAspect.method2();
return obj;
}
}
编写测试类
@Test
public void method(){
// 创建代理对象
jdkProxy jdkProxy = new jdkProxy();
// 创建目标对象
UserDao userDao = new UserDaoImpl();
// 从代理对象中获取增强后的目标对象
UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
// 执行方法
userDao.addUser();
userDao.deleteUser();
System.out.println("==============================================");
userDao1.addUser();
userDao1.deleteUser();
}
将jdk动态代理模式改装成springAop
去掉代理类由spring接管
更改切面类MyAspect
// 切面类
public class MyAspect implements MethodInterceptor{
// 以下方法称为增强方法
public void method1() {
System.out.println("检查账号是否正确");
}
public void method2() {
System.out.println("通过检查...");
}
// 此时代理方法在这里
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// TODO Auto-generated method stub
method1();
// 执行目标方法
Object obj = mi.proceed();
method2();
return obj;
}
}
编写配置文件
<!-- 1、目标类 -->
<bean id="userDao" class="com.bdqn.cn.dao.UserDaoImpl" />
<!-- 2、定义切面类 -->
<bean id="myAspect" class="com.bdqn.cn.aspect.MyAspect" />
<!-- 3、使用Spring代理工厂定义一个名称为userDaoProxy的代理对象 -->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定代理实现的接口 -->
<property name="proxyInterfaces" value="com.bdqn.cn.dao.UserDao" />
<!-- 指定目标对象 -->
<property name="target" ref="userDao" />
<!-- 指定切面植入环绕通知 -->
<property name="interceptorNames" value="myAspect" />
<!-- 指定代理方式,默认使用jdk动态代理 如果value值为true表示使用cglib-->
<property name="proxyTargetClass" value="false" />
</bean>
编写测试类
@Test
public void method2(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao ud = (UserDao)app.getBean("userDaoProxy");
ud.addUser();
ud.deleteUser();
}