AOP
Spring AOP:面象切面编程,即织入增强,以子类的形式去扩展及重写。核心通过代理类去实现,例如服务层中的一个Server类中有几个方法添加用户,删除用户,更新用户,查询用户信息,分别调用Dao层中添加用户,删除用户,更新用户,查询用户信息的方法,但在调用前需要做性能测试,日志记录,事务启动等动作。结束后需要做性能测试结果报告,日志结束,事务的提交等操作,发生异常时需要使用异常处理逻辑,此时将性能测试,日志记录,事务,及异常处理逻辑抽取出来,交由代理,还服务层一块纯净的空间,在调用Server类中的方法时,先由代理将事务等方法织入并执行。
实现核心:JDK动态代理和CGLib代理组成
两者的区别:
一、 JDK动态代理代理的目标类需要实现接口,而CGLib则不需要类去实现接口。
二、 JDK使用的是JAVA反射机制生成,而CGLib则是生成了一个新的子类。
织入的方式有三种:
a. 编译期织入,要求使用特殊的JAVA编译器。
b. 类装载期织入,要求使用特殊的类装载器。
c. 运行期织入,在运行期为目标类添加增强生成子类的方式。
Spring采用动态代理织入,而AspectJ采用的是编译期织入,类装载期织入。
切点五个位置:
a. @Before() 执行目标类方法前
b. @AfterReturning() 执行目标类方法后
c. @After() 无论如何都会执行
d. @AfterThrowing() 异常产生时执行
e. @Around() 有固定的格式,在方法执行前后,可取代@Before(),@AfterReturning()。其固定格式为:
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
System.out.println("进入方法");
Object retVal = pjp.proceed();
System.out.println("退出方法");
// stop stopwatch
return retVal;
}
注意:@Before()可接受目标类方法的传递参数。@AfterReturning()接受目标类方法返回值,做为其参数传递。@AfterThrowing()可接收发生的异常
Spring AOP实现具体步骤:
1. 编写Service层的接口。
2. 编写Service层的接口实现类。
3. 编写切面类及增强的方法。
4. 在配置文件中配置。
5. 调试。
package org.service.person;
public interface PeronService {
public void savePserson(String name);
public void updatePerson(String name,Integer personID);
public String getPersonName(Integer personID);
}
package org.service.person.imp;
import org.service.person.PeronService;
public class PersonServiceImp implements PeronService {
private String name = null;
public PersonServiceImp() {
}
public PersonServiceImp(String name) {
this.name = name;
}
public void savePserson(String name) {
System.out.println("savePserson方法");
}
public void updatePerson(String name, Integer personID) {
throw new RuntimeException("我是例外");
// System.out.println("updatePerson方法");
}
public String getPersonName(Integer personID) {
System.out.println("getPersonName方法");
return "xxxx";
}
public String getName() {
return this.name;
}
}
package org.service.person.intercep;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
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;
@Aspect
public class InterceptPersonservice {
@Pointcut("execution(* org.service.person..*(..))")
public void anyMethod() {
}
@Before("anyMethod() && args(name)")
public void doBefore(String name) {
System.out.println("我是前置增强:" + name);
}
@AfterReturning(pointcut = "anyMethod()", returning = "result")
public void doAfterReturning(String result) {
System.out.println("我是后置增强:" + result);
}
@After("anyMethod()")
public void doAfter() {
System.out.println("我是最终增强");
}
@AfterThrowing(pointcut = "anyMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
System.out.println("我是异常增强:" + e);
}
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
System.out.println("进入方法");
Object retVal = pjp.proceed();
System.out.println("退出方法");
// stop stopwatch
return retVal;
}
}
<?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"
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">
<!-- <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"
/> -->
<aop:aspectj-autoproxy>
<!-- Explicit testing the whitespace body variant here -->
</aop:aspectj-autoproxy>
<bean id="personServiceImp" class="org.service.person.imp.PersonServiceImp" />
<bean id="interceptPersonservice" class="org.service.person.intercep.InterceptPersonservice" />
</beans>
package org.junit.test;
import org.junit.Test;
import org.proxy.CGLibFactory;
import org.proxy.ProxyFactory;
import org.service.person.PeronService;
import org.service.person.imp.PersonServiceImp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringAOPTest {
@Test
public void springAOPTest() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"org/service/person/springAop.xml");
PeronService peronService = (PeronService) applicationContext
.getBean("personServiceImp");
peronService.savePserson("xx");
System.out.println("---------------------");
peronService.getPersonName(2);
System.out.println("---------------------");
peronService.updatePerson("xx", 2);
}
}
JDK编写代理类
package org.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.service.person.imp.PersonServiceImp;
public class ProxyFactory implements InvocationHandler{
private Object object;
public Object createProxyInstace(Object object){
this.object = object;
return Proxy.newProxyInstance(this.object.getClass().getClassLoader(), this.object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PersonServiceImp personServiceImp = (PersonServiceImp) this.object;
Object result = null;
// System.out.println(personServiceImp.getName());
if (personServiceImp.getName()!=null) {
result = method.invoke(this.object, args);
}
return result;
}
}
CGLib实现
package org.proxy;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.service.person.imp.PersonServiceImp;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibFactory implements MethodInterceptor{
private Object object;
public Object createCGLibInstace(Object object){
this.object = object;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.object.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
PersonServiceImp personServiceImp = (PersonServiceImp) this.object;
Object result = null;
// System.out.println(personServiceImp.getName());
if (personServiceImp.getName()!=null) {
result = arg3.invoke(this.object, arg2);
}
return result;
}
}
测试:JDK动态代理和CGLib代理
package org.junit.test;
import org.junit.Test;
import org.proxy.CGLibFactory;
import org.proxy.ProxyFactory;
import org.service.person.PeronService;
import org.service.person.imp.PersonServiceImp;
public class ProxyTest {
@Test
public void personProxyTest(){
ProxyFactory proxyFactory = new ProxyFactory();
PersonServiceImp personServiceImp = new PersonServiceImp();
PersonServiceImp personServiceImp2 = new PersonServiceImp("aaa");
PeronService peronService = (PeronService)proxyFactory.createProxyInstace(personServiceImp);
peronService.savePserson("xxx");
System.out.println("----------");
PeronService peronService2 = (PeronService)proxyFactory.createProxyInstace(personServiceImp2);
peronService2.savePserson("xxx");
}
@Test
public void cgLibTest(){
CGLibFactory cglibFactory = new CGLibFactory();
PersonServiceImp personServiceImp = new PersonServiceImp();
PersonServiceImp personServiceImp2 = new PersonServiceImp("aaa");
PersonServiceImp peronService = (PersonServiceImp)cglibFactory.createCGLibInstace(personServiceImp);
peronService.savePserson("xxx");
System.out.println("----------");
PersonServiceImp peronService2 = (PersonServiceImp)cglibFactory.createCGLibInstace(personServiceImp2);
peronService2.savePserson("xxx");
}
}
分享到:
相关推荐
3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑...
spring aop jar 包
描述一下Spring AOP? 在Spring AOP中关注点(concern)和横切关注点(cross-cutting concern)有什么不同? AOP有哪些可用的实现? Spring中有哪些不同的通知类型(advice types)? Spring AOP 代理是什么? 引介...
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
spring aop切面拦截指定类和方法实现流程日志跟踪 一般情况下,在不侵入业务代码的情况下,需要做流程日志跟踪是比较合理的 采用springaop切面思想
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
springaop依赖的jar包,spring版本2.5.6,如果需要,可以下载使用,欢迎各位评论指出不足
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
Spring源码最难问题:当Spring AOP遇上循环依赖.docx
spring aop的demo spring aop的demo
Spring AOP 入门 作者:廖雪峰
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
Spring AOP 日志管理 实例LoggingThrowsAdvice.java
Spring AOP 几个不同使用方法的完整例子,使用Junit4c测试, 在我的博客上有不同配置组合的说明,可以参考
Spring AOP的实现机制中文版,动态代理及原理,自定义类加载器
Spring AOP简单demo 入门级的 advice
springAOP详解
spring aop 经典例子(原创),无论新手还是老手,可以快速对Spring AOP有个总体的认识。基于JDK1.6,Spring2.0.5,Eclipse IDE。
springaop多数据库读写分离