算法-复杂度分析
复杂度分析 1. O n表示数据规模 O(f(n)) 表示运行算法所需要执行的指令数,和f(n)…
AOP Aspect Oriented Programing 面向切面编程 , AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存);
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码 ;
AspecJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入 。
AOP 底层使用的代理技术 : JDK动态代理(JDK1.3 引入) 和 CGlib的动态代理
原理: 针对内存中Class对象,使用类加载器 动态为目标对象实现接口的创建代理类
UserDAO:
public interface UserDAO {
void add();
void search();
}
MyJDKProxy:
package com.liuyao.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created By liuyao on 2018/5/10 15:19.
*/
public class MyJDKProxy implements InvocationHandler {
private UserDAO userDAO; //被代理对象
// 通过被代理对象构造代理类对象
public MyJDKProxy(UserDAO userDAO) {
this.userDAO = userDAO;
}
/**
* 使用JDK进行 动态代理
*
* @return
*/
public UserDAO createJDKProxy() {
return (UserDAO) Proxy.newProxyInstance(this.userDAO.getClass().getClassLoader(), this.userDAO.getClass().getInterfaces(), this);
}
@Override
// 访问被代理对象 任何方法,都和执行 invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 针对add方法进行增强
if (method.getName().equals("add")) {
System.out.println("记录日志...");
// 调用目标方法
return method.invoke(this.userDAO, args);
} else {
// 其他方法直接继续执行
return method.invoke(this.userDAO, args);
}
}
}
Test:
@Test
public void testJDKProxy() {
UserDAO userDAO = new UserDAOImpl();
MyJDKProxy myJDKProxy = new MyJDKProxy(userDAO);
UserDAO userDAOProxy = myJDKProxy.createJDKProxy();
userDAOProxy.add();
userDAOProxy.search();
}
运行结果:
原理 : CGlib采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题
ProductDAO:
public class ProductDAO {
public void addProduct() {
System.out.println("addProduct");
}
public void deleteProduct() {
System.out.println("deleteProduct");
}
}
MyCGLibProxy:
package com.liuyao.proxy.cglibproxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* Created By liuyao on 2018/5/10 16:05.
*/
public class MyCGLibProxy implements MethodInterceptor {
private ProductDAO productDAO; //目标对象
// 通过构造器传入被代理对象
public MyCGLibProxy(ProductDAO productDAO) {
this.productDAO = productDAO;
}
// 创建代理
public ProductDAO createCGLibProxy() {
// 创建代理核心对象
Enhancer enhancer = new Enhancer();
// 设置被代理类(为类创建子类)
enhancer.setSuperclass(this.productDAO.getClass());
// 设置回调函数
enhancer.setCallback(this);
// 返回代理(返回代理子类对象)
return (ProductDAO) enhancer.create();
}
@Override
// 被代理对象所有方法执行,都会调用intercept方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if (method.getName().equals("addProduct")) {
long start = System.currentTimeMillis();
Object res = methodProxy.invokeSuper(o, objects);
long end = System.currentTimeMillis();
System.out.println("addProduct 运行 " + (end - start));
return res;
} else {
return methodProxy.invokeSuper(o, objects);
}
}
}
Test:
@Test
public void test() {
ProductDAO productDAO = new ProductDAO();
MyCGLibProxy myCGLibProxy = new MyCGLibProxy(productDAO);
ProductDAO productDAOProxy = myCGLibProxy.createCGLibProxy();
productDAOProxy.addProduct();
productDAOProxy.deleteProduct();
}
运行结果:
Spring在运行期,生成动态代理对象,不需要特殊的编译器
Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入
1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
程序中应优先对接口创建代理,便于程序解耦维护
标记为final的方法,不能被代理,因为无法进行覆盖
JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
CGLib 是针对目标类生产子类,因此类或方法 不能使final的
Spring只支持方法连接点,不提供属性连接
复杂度分析 1. O n表示数据规模 O(f(n)) 表示运行算法所需要执行的指令数,和f(n)…
Jedis 连接 Redis 常见错误 1. 安装iptables,设置6379端口为外界可以访问 1.1 关闭firewall…