关于spring中面向切向编程的思想部分在上一篇博客中已经给出了链接,这里就不再赘述。这里只是着重补充一下其中的关键概念以及在工程代码中的具体实现。src目录中包含两个包,cn.itcast.dao和cn.itcast.jdk两个包,在第一个cn.itcast.dao包中有两个java文件,一个是目标类的接口,另一个是目标类的具体实现,目标类的代码如下所示:
package cn.itcast.dao;
//target目标类
public class UseDaoImpl implements UserDao{
@Override
poublic void save(){
System.out.println("save添加用户");
}
@Override
poublic void update(){
System.out.println("update修改用户");
}
@Override
poublic void delete(){
System.out.println("delete删除用户");
}
@Override
poublic void find(){
System.out.println("find查询用户");
}
}
以上代码中的目标类包含切入点和连接点,但是什么叫做切入点和连接点呢?
把上面的代码想象成一个面包,把这个面包切开,切面包的那个点就叫做切入点,切入以后为了使面包更加美味,我们需要往其中添加其他食材吧,那么这个食材对应的代码是什么呢?这些食材被封装在我们的切面类中,如下所示:
package cn.itcast.jdk;
//切面类(对应于食材的集合),在其中包含多个Advice(对应于具体的食材)
public class MyAspect{
//advice1
public void myBefore(){
System.out.println("方法执行前");
}
//advice2
public void myafter(){
System.out.println("方法执行后");
}
}
现在食材和面包都有了,下面就要开始“烹饪”了,烹饪的具体代码如下(通过使用Proxy实现动态代理):
package cn.itcast.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.UserDaoImpl;
public class MyBeanFactory{
public static UserDao getBean(){
//1、准备目标类(准备面包)
final UserDao userDao=new UserDaoImpl();
//2、创建切面类实例(准备其余所有食材)
final MyAspect myAspect=new MyAspect();
//3、使用代理类,进行增强(将食材放入面包的切入点中)
return(UserDao) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
new class[]{UserDao.class},
new InvocationHandler(){
@Override
public Object invoke(Object proxy,Method,Object[] args) throws Throwable{
//前增强
myAspect.myBefore();
//目标类的方式
Object obj=method.invoke(UserDao,args);
//后增强
myAspect.myAfter();
return obj;
}
});
}
}
下面将烹饪好的面包取出:
package cn.itcast.jdk;
import org.junit.Test;
import cn.itcast.dao.UserDao;
public class TestJDK {
@Test
public void demo01() {
// 1 从工厂获得指定的内容 (相当于spring获得,但此内容,是代理对象)
UserDao userDao = MyBeanFactory.getBean();
// 2 执行方法
userDao.save();
userDao.update();
userDao.delete();
userDao.find();
}
}
最终运行结果如下:
可见,目标类的每个切入点被切开以后,在每个切入点前后都依次执行了myAspect中的myBefore()和myAfter()方法,所以连接点是一个抽象的概念,可以理解为是食材和面包的连接欸部位的总和。