Spring对AOP的支持
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
目标类:
package com.aop.cglib;
public class UserService{
public void buy(String name) {
System.out.println(name+",买好洗衣粉,回家洗衣服去了..CGLib");
}
}
织入类
package com.aop.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* CGLib用底层字节码技术,可以为一个类创建子类,并子类中采用方法拦截技术"拦截"所以父类方法的调用,并且顺势"织入"我们需要的业务"逻辑代码".
* 简语--当一个类继承了cgblib类以后,实现类MethodInterceptor,在目标对象对象方法的时候就是进行拦截,并且织入逻辑代码
*/
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clz) {
enhancer.setSuperclass(clz);//设置创建子类的类,目标类
enhancer.setCallback(this);
return enhancer.create();//才用底层字节码技术,创建对象
}
@Override
//拦截所以业务的方法--代理类代用的方法
public Object intercept(Object obj, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
System.out.println("走到了收银台付钱了...CGLib");//织入横切业务逻辑
Object result = methodProxy.invokeSuper(obj, params);//执行代理类调用的方法
System.out.println("登记一下账目CGLib");//织入横切业务逻辑
return null;//返回对象
}
}
测试类
package com.aop.cglib;
public class Test {
public static void main(String[] args) {
//这个代理对象
CglibProxy proxy = new CglibProxy();
UserService userService = (UserService) proxy.getProxy(UserService.class);
userService.buy("mm");
}
}
JDK例子
接口:
package com.aop.jdk;
public interface IUserService {
public void buy(String name);
}
目标类:
package com.aop.jdk;
public class UserService implements IUserService{
@Override
public void buy(String name) {
System.out.println(name+",买好洗衣粉,回家洗衣服去了..JDK");
}
}
织入类
package com.aop.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WavingInvocationHandler implements InvocationHandler{
private Object target;
public WavingInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
System.out.println("走到了收银台付钱了...JDK");
Object obj = method.invoke(target, params);
System.out.println("登记一下账目JDK");
return obj;
}
}
测试类:
package com.aop.jdk;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
/** Aop
---jdk动态"代理"
1:目标对象
2:织入类
3:代理类
4:接口
---CGLIB动态"代理"
1:目标对象
2:织入类
3:代理类
*/
//目标类
IUserService userService = new UserService();
//织入类
WavingInvocationHandler handler = new WavingInvocationHandler(userService);
//代理类--增强的对象--proxyUser -代理商
IUserService proxyUser = (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), handler);
proxyUser.buy("MM");
}
}
简单的spring AOP
接口:
package com.aop.spring;
public interface IWaiter {
public void sayHello(String name);
public void server(String name);
}
目标类:
package com.aop.spring;
public class WaiterImpl implements IWaiter{
@Override
public void sayHello(String name) {
System.out.println("你好!"+name);
}
@Override
public void server(String name) {
System.out.println("服务于:"+name);
}
}
前置通知类
package com.aop.spring;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class GreetingBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] params, Object obj) throws Throwable {
String name = String.valueOf(params[0]);
System.out.println("早上好,"+name+",睡的可好");
}
}
bean.xml文件
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd" >
<!-- (advice增强类) -->
<bean id="advice" class="com.aop.spring.GreetingBeforeAdvice"></bean>
<!-- 目标类 -->
<bean id="target" class="com.aop.spring.WaiterImpl"></bean>
<!-- 代理工厂 -->
<!--
通过设定:optimize来决定你是否使用的代理模式:
true:cglib动态代理
false:jdk的动态代理(默认)
当设置true的时候:强制使用cgblib代理,对应单例模式,推荐使用它。dao,service,
对已其他的模式,一般推荐使用jdk的代理。原因是cglib,在创建代理对象的时候,是编译阶段发生的行为,而创建出的对象对象的运行速度较高。
jdk代理恰好相反。
单例模式就用:cgblib
多例模式都用:jdk
SpringAop:的底层就是通过JDK动态代理"或"CGLib动态代理为技术目标织入横切逻辑。
做aop:需要导入:
spring-aop-4.1.5.RELEASE.jar
spring-beans-4.1.5.RELEASE.jar
spring-context-4.1.5.RELEASE.jar
spring-context-support-4.1.5.RELEASE.jar
spring-core-4.1.5.RELEASE.jar
cglib引入的包:
cglib-nodep-2.1_3.jar
aop联盟:schmeAop
aopalliance-1.0.jar
aspectj:基于注解aop
aspectjweaver.jar
org.springframework.aop.MethodBeforeAdvice 前置通知:在目标方法之前,执行的业务逻辑 :MethodBeforeAdvice
org.springframework.aop.AfterReturningAdvice 后置通知:在目标方法之后,执行的业务逻辑
org.aopalliance.intercept.MethodInterceptor 环绕通知:目标方法执行前后,执行的业务逻辑(用的最多的)
org.springframework.aop.ThrowsAdvice 异常通知:执行目标方法出现异常,执行的业务逻辑(几乎很少使用)
org.springframework.aop.IntroductionInterceptor 引介通知.在目标类中添加了一些新的方法和属性的时候,执行的业务逻辑(几乎很少使用)
Aop:注解
schemeaop
服务员和顾客问好和服务.
1:早上好.XXX sayHello(String name)
2:对XXX提供服务. server(String name)
//采用spring的jdk动态代理
* 1:接口
* 2:织入类(通知类)
* 3:目标类
* 4:代理类
-->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.aop.spring.IWaiter"
p:interceptorNames="advice"
p:target-ref="target"
p:proxyTargetClass="true">
</bean>
</beans>
测试类:
package com.aop.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
/**
* SpringAop:的底层就是通过JDK动态代理"或"CGLib动态代理为技术目标织入横切逻辑。
* 做aop:需要导入:
* spring-aop-4.1.5.RELEASE.jar
spring-beans-4.1.5.RELEASE.jar
spring-context-4.1.5.RELEASE.jar
spring-context-support-4.1.5.RELEASE.jar
spring-core-4.1.5.RELEASE.jar
cglib引入的包:
cglib-nodep-2.1_3.jar
aop联盟:schmeAop
aopalliance-1.0.jar
aspectj:基于注解aop
aspectjweaver.jar
org.springframework.aop.MethodBeforeAdvice 前置通知:在目标方法之前,执行的业务逻辑 :MethodBeforeAdvice
org.springframework.aop.AfterReturningAdvice 后置通知:在目标方法之后,执行的业务逻辑
org.aopalliance.intercept.MethodInterceptor 环绕通知:目标方法执行前后,执行的业务逻辑(用的最多的)
org.springframework.aop.ThrowsAdvice 异常通知:执行目标方法出现异常,执行的业务逻辑(几乎很少使用)
org.springframework.aop.IntroductionInterceptor 引介通知.在目标类中添加了一些新的方法和属性的时候,执行的业务逻辑(几乎很少使用)
Aop:注解
schemeaop
服务员和顾客问好和服务.
1:早上好 XXX sayHello(String name)
2:对XXX提供服务. server(String name)
//采用spring的jdk动态代理
* 1:接口
* 2:织入类(通知类)
* 3:目标类
* 4:代理类
*/
public static void main(String[] args) {
//获取代理对象(目标对象的增强对象)
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/aop/spring/bean.xml");
// ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// WaiterImpl waiterImpl = (WaiterImpl) context.getBean("proxy");
IWaiter waiterImpl = (IWaiter) context.getBean("proxy");
waiterImpl.sayHello("MM");
System.out.println("====================");
waiterImpl.server("FF");
}
}