Spring两大特性,本篇我们对于AOP进行一个简单的实现。
AOP在Spring的世界里,算是独占半边天的节奏吧,何为AOP,其实就是对于OOP(Object-Oriented Programing)思想的补充和完善。OOP我们很熟悉,他是通过“抽象,封装,继承,多态”等思想,对万物进行一个定义。它强调了一种完整事物的自上而下的关系,但是对于具体粒度到每个事物内部的情况,我们则引出了AOP(Aspect-Oriented Programming),它采用一种“横切”的思想,对对象内部进行操作而又可以悄无声息,不留痕迹的将其复原,所以对于我们一些横切的需求,比如日志的功能带来了极大的方便。
对于annotation,是Java5的新特性,简单点就是注解功能,本篇使用的@Target,说明了Annotation所修饰的对象范围(被描述的注解可以用在什么地方)
Spring中AOP是通过AspectJ来实现的,原理图如下:
/* * 相当于写了个配置文件,说我这个类时Aspect的 */ @Aspect public class SecurityHandler { /* * 定义Pointcut,Pointcut的名称为addAddMethod(),此方法没有返回值和参数 * 该方法就是一个标示,不进行调用 */ @Pointcut("execution(* add*(..))") private void addAddMethod(){}; /* * Advice 在之前执行,所以是Before * 定义Advice,标示我们的Advice应用到哪些Pointcut订阅到Joinpoint上 */ @Before("addAddMethod()") //@After("addAddMethod()") private void checkSecurity() { System.out.println("-------checkSecurity-------"); } }
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 启用AspectJ对Annotation的支持 --> <aop:aspectj-autoproxy/> <bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/> <bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/> </beans>
public interface UserManager { // 添加方法一 public void addUser(String username, String password); // 删除方法 public void delUser(int userId); // 查询方法 public String findUserById(int userId); // 修改方法 public void modifyUser(int userId, String username, String password); // 添加方法二 public void addUsers(String username); }
public class UserManagerImpl implements UserManager { public void addUser(String username, String password) { // checkSecurity(); System.out.println("---------UserManagerImpl.add()--------"); } public void delUser(int userId) { // checkSecurity(); System.out.println("---------UserManagerImpl.delUser()--------"); } public String findUserById(int userId) { // checkSecurity(); System.out.println("---------UserManagerImpl.findUserById()--------"); return "霍霍"; } public void modifyUser(int userId, String username, String password) { // checkSecurity(); System.out.println("---------UserManagerImpl.modifyUser()--------"); } @Override public void addUsers(String username) { // TODO Auto-generated method stub System.out.println("----------UserManagerImp.addUsers()-----------"); } }
public class Client { public static void main(String[] args) { // 取得BeanFactory BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager = (UserManager)factory.getBean("userManager"); // 调用添加方法一 userManager.addUser("huohuo", "123"); // 调用添加方法二 userManager.addUsers("huhu"); } }最后测试的结果:
public class SecurityHandler { private void checkSecurity() { System.out.println("-------checkSecurity-------"); } }
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/> <bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/> <aop:config> <!-- 查找Aspect类 --> <aop:aspect id="securityAspect" ref="securityHandler"> <!-- 定义Pointcut --> <aop:pointcut id="addAddMethod" expression="execution(* add*(..))" /> <!-- 配置Advice实现 --> <aop:before method="checkSecurity" pointcut-ref="addAddMethod"/> </aop:aspect> </aop:config> </beans>最后运行结果等同。