一、概念:如果看得头疼,可以直接看总结,当然多了解没有坏处 面向方面(切面)编程(Aspect Oriented Programming) Spring的一个关键的组件就是 AOP框架。 尽管如此,Spring IoC容器并不依赖于AOP,这意味着可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring IoC容器更加完善。 Spring AOP的出现是为了取代 EJB中的事务机制,它有这种声明式的事务机制,其实AOP的这种思想早就已经有了,并不是一种什么新的技术,也并不是说专门由java这里来实现的。 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。
Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是对横切性关注点的抽象. joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器) Pointcut(切入点):所谓切入点是指我们要对哪些joinpoint进行拦截的定义. Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知 Target(目标对象):代理的目标对象 Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入. Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
二、为什么使用Aop 高度模块化,使得我们的系统更易实现和更易维护
使每个模块承担的责任更清晰,提高代码的可追踪性
解决设计时两难的局面,在不需改动原先代码的情况下推迟不必要的需求的实现
提高代码的重用性
加速系统的开发和部署,提高程序员的开发效率
降低系统开发的成本
三、应用范围: Persistence(持久化) Transaction management(事务管理) Security(安全) Logging,tracing,profiling and monitoring(日志,跟踪,优化,监控)
Debugging(调试) Authentication(认证) Context passing(上下文传递) Error/Exception handling(错误/异常处理)
Lazy loading(懒加载) Performance optimization(性能优化) Resource pooling(资源池) Synchronization(同步)
总结: 这些理论的看着太多了头疼,总结一下,Aop主要的作用:比如我们平时写事务管理或者记录日志的时候,是不是要在没每一个类里面都加或者调用公共类,我们的Aop就可以在你执行这个方法之前或者之后又或者中间来写入事务管理或者日志。 切面编程:其实大概意思也就是,不在原来的代码上做操作,还可以加入一些我们需要的东西,比如事务管理、日志、权限校验等。图我觉得说得很明白了吧。
首先我们来认识AOP的代理: Spring缺省使用JAVA 动态代理(dynamic proxies)来作为AOP的代理。这样任何接口都可以被代理。 Spring也支持使用CGLIB代理. 对于需要代理类而不是代理接口的时候CGLIB代理是很有必要的。 如果一个业务对象并没有实现一个接口,默认就会使用CGLIB。作为面向接口编程的最佳实践,业务对象通常都会实现一个或多个接口。
其次就是代理中的:静态代理(今天的主要任务),通过他们统一实现的接口制造一个拦截器,然后拦截它,在加东西进去,然后调用。 applicationContex.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <bean id="userDao1" class="spring.UserDaoImpl"></bean> <bean id="userDao2" class="spring.UserDaoImpl_2"></bean> <bean id="proxyHandler" class="spring.ProxyHandler"> <constructor-arg ref="userDao1"></constructor-arg> </bean> </beans>两个来试验的dao都实现了IUserDao这个借口,这个接口里面有两个方法,就是它们实现的那两个,我就发出来了。看这个两个一模一样的类。 UserDaoImpl:
package spring; public class UserDaoImpl implements IUserDao { public UserDaoImpl() { System.out.println("new UserDaoImpl() 实例化"); } @Override public void selectUser() { System.out.println("UserDaoImpl.selectUser..........11111"); } @Override public boolean insertUser(String username) { System.out.println("UserDaoImpl.insertUser("+username+")"); return true; } }UserDaoImpl2:
package spring; public class UserDaoImpl_2 implements IUserDao { public UserDaoImpl_2() { System.out.println("new UserDaoImpl_2() 实例化"); } @Override public void selectUser() { System.out.println("UserDaoImpl_2.selectUser..........22222"); } @Override public boolean insertUser(String username) { System.out.println("UserDaoImpl_2.insertUser("+username+")"); return true; } }静态代理类:ProxyHandler
package spring; /** * 静态代理:代理所有实现同一接口IUserDao的实现类 * @author Administrator * */ public class ProxyHandler implements IUserDao{ //实际对象 private IUserDao userDao; public ProxyHandler(IUserDao userDao) { this.userDao = userDao; } @Override public void selectUser() { System.out.println(userDao.getClass().getName() + ".selectUser()............日志记录开始"); //真正的核心逻辑代码,调用实际对象的方法 userDao.selectUser(); System.out.println(userDao.getClass().getName() + ".selectUser()............日志记录结束"); } @Override public boolean insertUser(String username) { System.out.println(userDao.getClass().getName() + ".insertUser("+username+")............日志记录开始"); //真正的核心逻辑代码,调用实际对象的方法 boolean result = userDao.insertUser(username); System.out.println(userDao.getClass().getName() + ".insertUser()............日志记录开始,返回结果:" + result); return result; } }test类:
package spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //加载解析applicationContext.xml //积极加载,在加载与解析xml的同时,即完成所有bean的实例化 ClassPathXmlApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); System.out.println("IOC容器加载完成"); ProxyHandler proxy = (ProxyHandler)factory.getBean("proxyHandler"); proxy.insertUser("张三"); proxy.selectUser(); } }