在介绍手动实现AOP之前我们需要了解几个知识点
业务代码和关注点代码,下面拖过一个例子来形象的解释着二者的意思
关注点代码,就是指重复执行的代码。
业务代码与关注点代码分离,关注点代码写一次即可;
开发者只需要关注核心业务,运行时期,执行核心业务代码时候通过代理动态植入关注点代码;
接下来来介绍介个名词
关注点:重复代码就叫做关注点;
切面:关注点形成的类,就叫切面(类), 面向切面编程,就是指 对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。
切入点:执行目标对象方法,动态植入切面代码。可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。
下面通过一个案例来手动实现AOP(动态代理实现)
首先写一个接口
package com.Demo5;
public interface IUserDao {
public void save();
}
然后写一个类去实现这个接口
package com.Demo5;
import org.springframework.stereotype.Component;
@Component("userDao")
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("-----------开启连接-----------");
}
}
其次在写一个MyAop类,主要存放重复的代码
package com.Demo5;
import org.springframework.stereotype.Component;
//通过注解直接配置对象
@Component
public class MyAop {
public void beginTran(){
System.out.println("...............开启事务");
}
public void commite(){
System.out.println("...............提交事务");
}
}
然后写一个代理类
package com.Demo5;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
private static MyAop aop;
private static Object target;
public static Object getProxyFactory(Object _target,MyAop _aop){
//目标对象
target = _target;
aop = _aop;
//在目标方法去传入目标参数和AOP参数
return Proxy.newProxyInstance(target.getClass().getClassLoader()
, target.getClass().getInterfaces()
, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
aop.beginTran();
//通过反射获取方法返回值
Object resultValue = method.invoke(target,args);
aop.commite();
return resultValue;
}
});
}
}
然后再去配置bean1.xml
<?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"
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">
<!--开启注解扫描-->
<context:component-scan base-package="com.Demo5"></context:component-scan>
<!--配置工厂对象-->
<!--我们的方法是静态的所以需要通过类名来调用方法-->
<bean id="userProxy" class="com.Demo5.ProxyFactory" factory-method="getProxyFactory">
<!--因为我们写的getProxyFactory方法有2个参数所以需要配置参数-->
<constructor-arg index="0" ref="userDao"></constructor-arg>
<constructor-arg index="1" ref="myAop"></constructor-arg>
</bean>
</beans>
最后写一个测试类
package com.Demo5;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test3 {
public static void main(String []args){
ApplicationContext ap = new ClassPathXmlApplicationContext("bean1.xml");
IUserDao proxy = (IUserDao) ap.getBean("userProxy");
proxy.save();
}
}
运行结果如下