什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
前提:要实现AOP的模拟就要知道动态代理,Spring中使用了两种动态代理方式,一种是基于JDK的动态代理,一种是基于CGlib的动态代理。为什么会有两种,那是因为JDK的动态代理只能是
针对接口。
先看下面的代码dao层
Java代码
1. package com.lbx.dao;
2.
3. import com.lbx.model.User;
4.
5. public interface UserDAO {
6. public void save(User user);
7. //public void delete();
8. }
dao实现层
Java代码
1. package com.lbx.dao.impl;
2.
3. import com.lbx.dao.UserDAO;
4. import com.lbx.model.User;
5.
6. public class UserDAOImpl implements UserDAO {
7.
8. @Override
9. public void save(User user) {
10.
11. System.out.println("a user saved!!!");
12.
13. }
14.
15. /*public void delete(){
16. System.out.println("UserDAOImpl.delete()");
17. }
18. */
19. }
现在我们要在User的save之前和之后做一些处理(拦截器),我们先看一种最简单的方法(在类中加代码)
Java代码
1. package com.lbx.dao.impl;
2.
3. import com.lbx.dao.UserDAO;
4. import com.lbx.model.User;
5.
6. public class UserDAOImpl1 implements UserDAO {
7.
8. @Override
9. public void save(User user) {
10.
11. System.out.println("method start....");
12.
13. System.out.println("a user saved!!!");
14.
15. System.out.println("method stoped...");
16.
17. }
18.
19. }
显然,这是可以的,但是这样明显就不好,第一代码没可重用性,第二这是在知道源码的情况下,现实中我们有很多情况都不知道源码,在这种情况下,明显这方式就不行了。下面就是第二
种解决方案:
Java代码
1. package com.lbx.dao.impl;
2.
3. import com.lbx.model.User;
4.
5. public class UserDAOImpl2 extends UserDAOImpl{
6.
7. public void save(User user) {
8.
9. System.out.println("method start....");
10. super.save(user);
11. System.out.println("method stoped.....");
12.
13. }
14.
15. }
先让一个类实现了那个接口,然后要用的类继承那个实现类,这样也可以达到目的(其实这就是一种“组合模式”),这种方式在一定的程度上是利用的资源,代码的重用性。但是还是不好
,当我们要做很多的处理的时候,这样我们就要组合和多的类,明显就不好。下面是第三种:使用动态代理。 先看处理方法(拦截器)
Java代码
1. package com.lbx.interceptor;
2.
3. public class UserInterceptor {
4.
5. //第一个拦截方法
6. public void method1(){
7. System.out.println("UserInterceptor.method1()");
8. }
9.
10. //第二个拦截方法
11. public void method2(){
12. System.out.println("UserInterceptor.method2()");
13. }
14.
15. }
产生代理的类,实现InvocationHandler接口
Java代码
1. package com.lbx.interceptor;
2.
3. import java.lang.reflect.InvocationHandler;
4. import java.lang.reflect.Method;
5.
6. public class ProxyHandler implements InvocationHandler {
7.
8. //创建需要代理的目标对象
9. private Object targer;
10. //创建拦截器的实例
11. UserInterceptor u = new UserInterceptor();
12.
13. public Object invoke(Object proxy, Method method, Object[] args)
14. throws Throwable {
15. Object result = null;
16.
17. //if(method.getName().equals("save")){
18. u.method1();
19. result = method.invoke(targer, args);
20. u.method2();
21. //}else{
22. //result = method.invoke(targer, args);
23. //}
24.
25. return result;
26. }
27.
28. //用于设置传人目标对象的方法
29. public void setTarger(Object o){
30. this.targer = o;
31. }
32.
33. }
获得代理的实例类
Java代码
1. package com.lbx.interceptor;
2.
3. import java.lang.reflect.Proxy;
4.
5. import com.lbx.dao.impl.UserDAOImpl;
6.
7. public class UserProxyFactory {
8.
9. public static Object getProxy(Object object){
10. ProxyHandler p = new ProxyHandler();
11. p.setTarger(object);
12. return Proxy.newProxyInstance(UserDAOImpl.class.getClassLoader(), object.getClass().getInterfaces(), p);
13. }
14.
15. }
服务层使用动态代理
Java代码
1. package com.lbx.service;
2.
3. import com.lbx.dao.UserDAO;
4. import com.lbx.dao.impl.UserDAOImpl;
5. import com.lbx.interceptor.UserProxyFactory;
6. import com.lbx.model.User;
7.
8. public class UserService {
9.
10. //private UserDAO userDAO = new UserDAOImpl1(); //第一种就是写死,直接在方法里写
11. //private UserDAO userDAO = new UserDAOImpl2(); //第二种就是通过继承来实现(方法执行前后加一些业务逻辑)
12. //private UserDAO userDAO = new UserDAOImpl3(); //第三种是通过组合来完成的
13. UserDAO userDAO = new UserDAOImpl();
14. UserDAO u = null;
15.
16. Object object = UserProxyFactory.getProxy(userDAO);
17.
18. /*public UserDAO getUserDAO() {
19. return userDAO;
20. }
21.
22. public void setUserDAO(UserDAO userDAO) {
23. this.userDAO = userDAO;
24. }*/
25.
26. /*public void add(User user){
27. this.userDAO.save(user);
28. }*/
29.
30. public void add(User user){
31. if(object instanceof UserDAO){
32. u = (UserDAO)object;
33. }
34. u.save(user);
35. //u.delete();
36. }
37.
38. }