AOP的底层实现:
1.底层实现就是代理机制:
2.JDK动态代理:
原理:并没有使用多余的技术,纯粹的原java方式,类运用,即生成了一个接口的实现类.
JDK动态代理的使用: 添加Proxy类,一般会继承: InvocationHandler接口生成invoke方法。
static Object
接口 | newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ClassLoader :类的加载器. Class[] :实现的所有接口. InvocationHandler :处理接口.
Object invoke(Object proxy,Method method,Object[] args); Object:代理对象. Method:执行的方法. Object[]:执行这个方法的参数列表. |
2.1.调用真实对象的方法的时候;
* UserDao(接口)---->UserDaoImpl(实现类)
* 对UserDaoImpl生成一个代理类.
* UserDao userDao = Proxy.newProxyInstance(..);
* userDao.add();
* userDao.update();
***** 都相当于调用了InvocationHandler中的invoke()方法.
2.2.JDK动态代理的代码实现:
生成代理类==>
public class JdkProxy implements InvocationHandler{
private UserDao userDao;
public JdkProxy(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy(){
Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
return (UserDao) proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 判断执行的方法
// 对add方法进行增强
if("add".equals(method.getName())){
// 增强
System.out.println("增强的代码...");
return method.invoke(userDao, args);
}else{
// 不增强
return method.invoke(userDao, args);
}
}
}
测试主体
==>package cn.green.demo;
import org.junit.Test;
public class TestCase {
@Test
public void demo01(){
UserDao userDao = new UserDaoImpl();
UserDao userProxy = new JdkProxy(userDao).createProxy();
userProxy.add();
userProxy.delete();
}
}
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
<bean id="userDao" class="cn.green.demo.UserDaoImpl"></bean>
<bean id="jdkProxy" class="cn.green.demo.JdkProxy"></bean>
</beans>
3. CGLIB的代理:
JDK的动态代理有局限性:类必须实现接口,才能生成代理.(一个类没有实现接口,JDK无法生成代理对象.)
CGLIB代理:可以对没有实现接口的类生成代理.
CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(Persistent Object 持久化对象)字节码的动态生成。
* Hibernate :javassist
原理:
* 通过字节码技术,对这个类生成了一个子类对象.
package cn.itcast.spring3.demo2;
public class ProductDao {
public void add(){
System.out.println("添加商品...");
}
public void update(){
System.out.println("修改商品...");
}
public void delete(){
System.out.println("删除商品...");
}
public void find(){
System.out.println("查询商品...");
}
}
package cn.green.demo1;
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 CglibProxy implements MethodInterceptor {
private OrderDao orderDao;
public CglibProxy(OrderDao orderDao){
this.orderDao = orderDao;
}
//生成代理的方法
public OrderDao createProxy(){
//CGLIB核心对象
Enhancer enhancer = new Enhancer();
//原理:对这个类生成一个子类对象
//设置父类
enhancer.setSuperclass(orderDao.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理对象
return (OrderDao) enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if("add".equals(method.getName())){
System.out.println("方法前增强代码===============");
Object obj = methodProxy.invokeSuper(proxy, args);
System.out.println("方法后增强代码===============");
return obj;
}else{
return methodProxy.invokeSuper(proxy, args);
}
}
}
package cn.green.demo1;
import org.junit.Test;
public class TestDemo {
@Test
public void test01(){
OrderDao orderDao = new OrderDao();
OrderDao proxy = new CglibProxy(orderDao).createProxy();
proxy.add();
proxy.delete();
proxy.update();
proxy.find();
}
}
<?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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="orderDao" class="cn.green.demo1.OrderDao"></bean>
<bean id="cglibProxy" class="cn.green.demo1.CglibProxy"></bean>
</beans>
方法前增强代码===============
add run....
方法后增强代码===============
delete run....
update run....
find run....
4.Spring中使用这两种技术完成代理(AOP):
* 如果类实现了接口,使用JDK动态代理,为你生成代理对象.
* 如果类没有实现接口,使用CGLIB动态代理,生成代理对象.
总结:
Spring在运行期,生成动态代理对象,不需要特殊的编译器
Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入
1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
* 程序中应优先对接口创建代理,便于程序解耦维护
3.标记为final的方法,不能被代理,因为无法进行覆盖
JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
CGLib 是针对目标类生产子类,因此类或方法 不能使final的
4.Spring只支持方法连接点,不提供属性连接.