AOP的实现有三种方式:java
l aop底层将采用代理机制进行实现。spring
l 接口 + 实现类 :spring采用 jdk 的动态代理Proxy。express
l 实现类:spring 采用 cglib字节码加强。编程
JDK动态代理 对“装饰者”设计模式 简化。使用前提:必须有接口设计模式
1.目标类:接口 + 实现类框架
2.切面类:用于存通知 MyAspectide
3.工厂类:编写工厂生成代理函数
4.测试测试
UserService.javaspa
package com.zk.a_jdk; public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.a_jdk; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("proxy addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("proxy updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("proxy deleteUser"); } }
MyAspect.java
package com.zk.a_jdk; public class MyAspect { public void before(){ System.out.println("鸡头"); } public void after(){ System.out.println("牛后"); } }
package com.zk.a_jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanFactory { //手工代理 public static UserService createService(){ //1.目标类 final UserService userservice=new UserServiceImpl(); //2.切面类 final MyAspect myAspect=new MyAspect(); //3.代理类:将目标类(切入点)和切面类(通知)结合-->切面 //Proxy.newProxyInstance /* * 参数一:loader类加载器,动态代理类,运行时建立,任何类都须要类加载器将其加载至内存。 * 通常状况下:当前类,class.getClassLoader(); * 目标类实例:getClass().get... * 参数二:interfaces,代理类须要实现的全部接口 * 方式一:目标类实例.getClass().getInterfaces();注意:只能得到本身的接口,得到不到父元素的接口 * 方式二:new Class[]{UserService.class} * 例如:jdbc驱动 * 参数三:InvocationHandler 处理类,接口,必须进行实现类,通常采用匿名内部类 * 提供invoke方法,代理类每个方法执行时,都将去调用invoke * 参数三.1.Object proxy代理对象 * 参数三.2.Method method 代理对象当前方法的描述对象(反射) * 执行方法方法名:method.getName(); * 执行方法:method.invoke(对象,实际参数) * 参数三.3 Object[] args 方法实际参数 */ UserService proxyService=(UserService)Proxy.newProxyInstance (MyBeanFactory.class.getClassLoader(), userservice.getClass().getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub //前执行 myAspect.before(); //执行目标类的方法 Object obj=method.invoke(userservice, args); //后执行 myAspect.after(); return null; } }); return proxyService; } }
package com.zk.a_jdk; import org.junit.Test; public class TestJDK { @Test public void test(){ UserService userservice=MyBeanFactory.createService(); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
运行效果:
l 没有接口,只有实现类。
l 采用字节码加强框架 cglib,在运行时 建立目标类的子类,从而对目标类进行加强。
l 导入jar包:
UserService.java
package com.zk.a_jdk; public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.a_jdk; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("proxy addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("proxy updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("proxy deleteUser"); } }
MyAspect.java
package com.zk.a_jdk; public class MyAspect { public void before(){ System.out.println("鸡头"); } public void after(){ System.out.println("牛后"); } }
package com.zk.b_cglib; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class MyBeanFactory { //手工代理 public static UserService createService(){ //1.目标类 final UserServiceImpl userservice=new UserServiceImpl(); //2.切面类 final MyAspect myAspect=new MyAspect(); /*3.代理类 * 采用字节码加强框架-cglib,程序运行时建立目标类的子类,从而对目标类进行加强 * 导入jar包 * intercept等效于jdk中invoke方法 * 参数一二三 与invoke相同 * 参数四方法的代理 */ Enhancer enhance=new Enhancer(); //肯定父类 enhance.setSuperclass(userservice.getClass()); enhance.setCallback(new MethodInterceptor(){ //设置回调函数,MethodInterceptor接口等效 jdk InvocationHandler接口 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodproxy) throws Throwable { // TODO Auto-generated method stub //前before myAspect.before(); //执行目标类的方法 Object obj=method.invoke(userservice, args); //执行代理类的父类 methodproxy.invokeSuper(proxy, args); //后after myAspect.after(); return null; } }); //建立代理 UserServiceImpl proxyservice=(UserServiceImpl) enhance.create(); return proxyservice; } }
package com.zk.b_cglib; import org.junit.Test; public class Testcglib { @Test public void test(){ UserService userservice=MyBeanFactory.createService(); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
运行效果图:
让spring 建立代理对象,从spring容器中手动的获取代理对象。
导入jar包:
AOP:AOP联盟(规范)、spring-aop (实现)
UserService.java
public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.springAop; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("deleteUser"); } }
/** * 切面类中肯定通知,须要实现不一样接口,接口就是规范,从而就肯定方法名称。 * * 采用“环绕通知” MethodInterceptor * */ public class MyAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手动执行目标方法 Object obj = mi.proceed(); System.out.println("后3"); return obj; } }
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!-- 建立目标类 --> <bean id="userserviceid" class="com.zk.factorybean.UserServiceImpl"></bean> <!-- 建立切面类 --> <bean id="aspectid" class="com.zk.factorybean.MyAspect"></bean> <!-- 建立代理类 使用工厂bean factorybean,底层调用getObject(), 返回特殊bean ProxyBeanFactory用于建立代理工厂bean,生成特殊代理对象 interface肯定接口 经过Array肯定多个值 只有一个值时,value="" target肯定目标类 interceptorNames:通知切面类名称,类型String[],若是设置一个值, value="" optimize:强制使用cglib <property name="optimized value="true"></property> 底层机制: 若是目标类有接口,采用jdk代理 若是没有接口,采用cglib代理 若是声明式optimize=true,都使用cglib --> <bean id="proxyServiceid" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="com.zk.factorybean.UserService"></property> <property name="target" ref="userserviceid"></property> <property name="interceptorNames" value="aspectid"></property> </bean> </beans>
package com.zk.factorybean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Testfactorybean { @Test public void test(){ String path="com/zk/factorybean/ApplicationContext.xml"; ApplicationContext ac=new ClassPathXmlApplicationContext(path); UserService userservice=(UserService) ac.getBean("proxyServiceid"); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
运行效果:
从spring容器得到目标类,若是配置aop,spring将自动生成代理。
要肯定目标类,aspectj 切入点表达式,导入jar包spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
UserService.java
public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.springAop; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("deleteUser"); } }
/** * 切面类中肯定通知,须要实现不一样接口,接口就是规范,从而就肯定方法名称。 * * 采用“环绕通知” MethodInterceptor * */ public class MyAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手动执行目标方法 Object obj = mi.proceed(); System.out.println("后3"); return obj; } }
<?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:p="http://www.springframework.org/schema/p" 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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 建立目标类 --> <bean id="userserviceid" class="com.zk.springAop.UserServiceImpl"></bean> <!-- 建立切面类 --> <bean id="aspectid" class="com.zk.springAop.MyAspect"></bean> <!-- Aop编程 1.导入命名空间 2.使用<aop:config>进行配置 proxy-target-class="true"声明是使用cglib代理 <aop:pointcut>:切入点,从目标对象上获取具体的方法 <aop:advisor>特殊的切面,只有一个通知和一个切入点 advise-ref 通知引用 pointcut-ref 切入点引用 advisor通知 3.切入点表达式 execution(* com.zk.springAop.*.*(..)) 选择方法 *表示返回值任意 包 类名任意. 方法名任意 . 参数任意 . --> <aop:config> <aop:pointcut expression="execution(* com.zk.springAop.*.*(..))" id="myPointCut"/> <aop:advisor advice-ref="aspectid" pointcut-ref="myPointCut"/> </aop:config> </beans>