AOP(aspect oriented programming)面向切面编程。
大致意思是在方法的执行过程中织入其他要执行的方法。
项目结构图
先介绍一下通过代理的方式实现aop,几个文件和上一篇一样,再贴一遍方便观看
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.model; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.dao; import com.ouc.wkp.model.User; public interface UserDAO { public void save(User user); public void delete(); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.dao.impl; import org.springframework.stereotype.Component; import com.ouc.wkp.dao.UserDAO; import com.ouc.wkp.model.User; @Component("u") public class UserDAOImpl implements UserDAO { @Override public void save(User user) { // Hibernate // JDBC // XML // NetWork System.out.println("user saved!"); // throw new RuntimeException(); } @Override public void delete() { // TODO Auto-generated method stub } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import com.ouc.wkp.dao.UserDAO; import com.ouc.wkp.model.User; @Component("userService") public class UserService { private UserDAO userDAO; @PostConstruct public void init() { System.out.println("init"); } public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } // @Autowired @Qualifier("u") @Resource(name = "u") public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } @PreDestroy public void destroy() { System.out.println("destroy"); } }
然后是一个代理类,继承自InvocationHandler
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogIntercepter implements InvocationHandler{ private Object target; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public void beforeMethod(Method m){ System.out.println(m.getName()+" start"); } public void afterMethod(Method m){ System.out.println(m.getName()+" end"); } public Object invoke(Object proxy,Method m,Object[] args) throws Throwable{ beforeMethod(m); m.invoke(target, args); afterMethod(m); return null; } }
然后再测试类中进行如下调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Test public void testProxy() { UserDAO userDAO = new UserDAOImpl(); LogIntercepter li = new LogIntercepter(); li.setTarget(userDAO); UserDAO userDAOProxy = (UserDAO) Proxy.newProxyInstance(userDAO .getClass().getClassLoader(), userDAO.getClass() .getInterfaces(), li); System.out.println(userDAOProxy.getClass()); userDAOProxy.delete(); userDAOProxy.save(new User()); }
运行结果
然后介绍通过xml配置文件实现aop
使用aop需要一下
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop -->
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy />
还需要这个开启对com.ouc.wkp包下面的扫描
<context:component-scan base-package="com.ouc.wkp"></context:component-scan>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <context:annotation-config /> <!-- 使用注解需要下面四条 --> <!-- xmlns:context="http://www.springframework.org/schema/context" --> <!-- http://www.springframework.org/schema/context --> <!-- http://www.springframework.org/schema/context/spring-context-3.1.xsd"> --> <!-- <context:annotation-config /> --> <!-- 使用aop需要一下 --> <!-- xmlns:aop="http://www.springframework.org/schema/aop" --> <!-- http://www.springframework.org/schema/aop --> <!-- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> --> <!-- <aop:aspectj-autoproxy /> --> <!-- 扫描 --> <context:component-scan base-package="com.ouc.wkp"></context:component-scan> <aop:aspectj-autoproxy /> <bean id="logIntercepter2" class="com.ouc.wkp.aop.LogIntercepter2"></bean> <aop:config> <!-- <aop:pointcut expression="execution(public * com.ouc.wkp.service..*.add(..))" id="servicePointcut"/> --> <!-- <aop:aspect id="logAspect" ref="logIntercepter"> --> <!-- <aop:before method="before" pointcut="servicePointcut"/> --> <!-- </aop:aspect> --> <aop:aspect id="logAspect" ref="logIntercepter2"> <aop:before method="before" pointcut="execution(public * com.ouc.wkp.service..*.add(..))" /> </aop:aspect> </aop:config> </beans>
<bean id="logIntercepter2" class="com.ouc.wkp.aop.LogIntercepter2"></bean>
<aop:config>
<!-- <aop:pointcut expression="execution(public * com.ouc.wkp.service..*.add(..))"
id="servicePointcut"/> -->
<!-- <aop:aspect id="logAspect" ref="logIntercepter"> -->
<!-- <aop:before method="before" pointcut="servicePointcut"/> -->
<!-- </aop:aspect> -->
<aop:aspect id="logAspect" ref="logIntercepter2">
<aop:before method="before"
pointcut="execution(public * com.ouc.wkp.service..*.add(..))" />
</aop:aspect>
</aop:config>
看下面这段 第一行声明了一个代理切入类(表达不准确)
<aop:pointcut expression="execution(public * com.ouc.wkp.service..*.add(..))"
id="servicePointcut"/>标识定义一个切入点pointcut。
<aop:before method="before" pointcut="servicePointcut"/>表示before织入这个切入点。
execution(public * com.ouc.wkp.service..*.add(..))代表com.ouc.wkp.service包下的任意包的任意类的add方法。
然后我们看代理切入类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class LogIntercepter2 { // @Pointcut("execution(public * com.ouc.wkp.service..*.add(..))") public void myMethod(){}; // @Before("myMethod()") public void before() { System.out.println("method before"); } // @AfterReturning("execution(public * com.ouc.wkp.dao..*.*(..))") public void afterReturning(){ System.out.println("method after returning"); } // @AfterThrowing("myMethod()") public void afterThrowing(){ System.out.println("method after throwing"); } // @Around("myMethod()") public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("method around start"); pjp.proceed(); System.out.println("method around end"); } }
类的开头需要加上
@Aspect
@Component
测试方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Test public void testAdd() throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "beans.xml"); UserService service = (UserService) ctx.getBean("userService"); User user = new User(); user.setUsername("qqq"); user.setPassword("123ppp"); //是一个代理 System.out.println(service.getClass()); service.add(user); ctx.destroy(); }
运行结果
我们看到我们获得的userservice实质上是一个代理类
最后介绍通过注解实现aop,LogIntercepter2的代码再贴一遍.
beans.xml里面的<aop:config>可以注释掉
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ouc.wkp.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class LogIntercepter2 { @Pointcut("execution(public * com.ouc.wkp.service..*.add(..))") public void myMethod(){}; @Before("myMethod()") public void before() { System.out.println("method before"); } @AfterReturning("execution(public * com.ouc.wkp.dao..*.*(..))") public void afterReturning(){ System.out.println("method after returning"); } @AfterThrowing("myMethod()") public void afterThrowing(){ System.out.println("method after throwing"); } @Around("myMethod()") public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("method around start"); pjp.proceed(); System.out.println("method around end"); } }
@Pointcut("execution(public * com.ouc.wkp.service..*.add(..))")
public void myMethod(){};表示定义一个切入点
@Before("myMethod()")表示在方法执行前执行注解下面的方法 myMethod()为上面定义的切入点
后面的注解见名知意
运行结果
感觉还是很神奇的 以前一直不理解什么是面向切面。现在简单了解了一下觉得很有趣,但是还是无法用语言准确表达出来= =
下一篇介绍spring整合hibernate