1.JDK动态代理方式实现
public static UserService createService(){ //目标类 final UserService userService = new UserServiceImp(); //切面类 final MyAspect myAspect = new MyAspect(); /** * 代理类: * class Proxy{ * public void addUser(){ * invoke(this,addUser,args) * } * public void deleteUser(){ * invoke(this,addUser,args) * } * } * * classLoader:类加载器,动态代理类在运行时创建,任何类都需要类加载器将其加载到内存。 * 一般使用当前类的类加载器 * interfaces:代理类需要实现的所有接口 * 方式1:userService.getClass().getInterfaces() * 方式2:new Class[]{UserService.class} * InvocationHandler:处理类,接口,匿名内部类 * invoke方法,代理类的每个方法执行时,都会调用一次该方法 * proxy:代理对象 * method:代理对象执行的方法的描述对象 * 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 { myAspect.before(); Object obj = method.invoke(userService,args); myAspect.after(); return obj ; } }); return proxyService; }
2.采用字节码增强的框架,在运行时创建目标类的子类,从而实现增强
2.1 导入jar包
核心:hibernate\lib\bytecode\cglib\cglib-2.2.jar
依赖:struts2.3.15.4\struts-2.3.15.3\lib\asm-3.3.jar
spring-core...jar已经整合了这两个jar包
3. AOP联盟通知类型
AOP联盟为通知定义了org.aopalliance.aop.Advice
环绕通知,必须手动执行目标方法
try{
//前置通知
//执行目标方法
//后置通知
}catch(){}
4. spring编写代理:半自动
4.1 让spring去创建代理对象,从spring容器手动获取代理对象
导入jar包:4+1
AOP jar包:AOP联盟(规范)spring-framework-3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0\com.springsource.org.aopalliance-1.0.0.jar
spring-aop(实现)spring-framework-3.2.0.RELEASE\libs\spring-aop-3.2.0.RELEASE.jar
<!-- bean definitions here 创建目标类 --> <bean id="userService" class="c_proxy_factoryBean.UserServiceImp"></bean> <bean id="myAspect" class="c_proxy_factoryBean.MyAspect"></bean> <!-- 使用spring的工厂bean,返回代理对象 --> <bean id="proxyUserService" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 设置接口 确定接口,是个数组,使用array设置,如果只有一个值时,可以使用value配置 --> <property name="interfaces"> <array> <value>c_proxy_factoryBean.UserService</value> </array> </property> <!--设置目标类--> <property name="target" ref="userService"></property> <!-- 设置通知 是个String数组,使用array设置,如果只有一个值时,可以使用value配置 --> <property name="interceptorNames" value="myAspect"></property> <!--强制使用cglib--> <property name="optimize" value="true"></property> </bean>
底层机制:
如果没有设置接口,则使用cglib方式
如果设置接口,默认使用JDK代理方式
可以强制使用cglib方式
5.spring AOP编程,全自动
从spring容器中正常获取目标类,如果配置了AOP,spring自动生成代理类
必须确定目标类,支持aspectJ切入点表达式,导入jar包spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE\com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
目标类-->pointcut(切入点) + 通知(advicor)--》advicor(切面)
excution() || excution()
public class MyAspect implements MethodInterceptor{ @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("before method..."); Object obj = methodInvocation.proceed(); System.out.println("after method..."); return obj; } }
<!-- bean definitions here 创建目标类 --> <bean id="userService" class="d_springAop.UserServiceImp"></bean> <bean id="bookService" class="d_springAop.BookService"></bean> <bean id="myAspect" class="d_springAop.MyAspect"></bean> <!--spring AOP,导入命名空间,是否使用cglib--> <aop:config proxy-target-class="true"> <!-- pointcut:切入点,目标类的方法 advicor:特殊的切面,只有一个通知和一个切入点,组织切入点和通知(增强) --> <!--切入点表达式--> <aop:pointcut id="myPointcut" expression="execution(* d_springAop.*.*(..))" /> <aop:advisor advice-ref="myAspect" pointcut-ref="myPointcut" /> </aop:config>
6. aspectJ
6.1 介绍
aspectJ是基于java的AOP框架
spring2.0后支持AspectJ切入点表达式
用途:自定义开发,代码植入
6.2 基于xml
6.3 基于注解