Spring中IOC和AOP的实现原理
IOC:java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,在使用其他的合作对象时,均要使用像new object() 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关心业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。IOC是...
IOC:
java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,在使用其他的合作对象时,均要使用像new object() 这样的语法来完成合作对象的创建。而IOC的思想说白了就是由Spring容器来实现对象的创建管理工作。我们只需要关心业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。
IOC是基于java的反射机制以及工厂模式实现的。具体可以看下这两篇文章,https://www.cnblogs.com/Eason-S/p/5851078.html和http://blog.csdn.net/liushuijinger/article/details/35978965,写的都很好
工场:各类都实现了某一接口,并提供一个工场类,根据传入参数的不同来创建不同的对象
反射:可以根据类名获取该类实例, Class.forName(ClassName).newInstance()
在项目启动时首先获取class 对应name和beanDefinition,然后通过beanDefinition创建实例,以类似键值对的方式将name和bean实例存储在spring上下文容器中,当需要使用时直接利用getBean(String beanName)从容器中获取对应的实例。
AOP主要是使用动态代理实现 https://www.cnblogs.com/lcngu/p/5339555.html,https://www.cnblogs.com/cenyu/p/6289209.html这个讲代理的也挺好
AOP(面向切面编程),在业务处理过程之前或之后总会有一些公共行为比如像权限认证、事务处理、打印日志等等,我们将那些公共行为封装到一个可重用模块,这些公共行为叫做切面,而被环绕的业务代码叫做切点,环绕切点的一系列操作均是对切点的增强处理。
JDK动态代理(被代理的类需要实现一个接口):中使用InvocationHandler接口和Proxy类来实现,在InvocationHandler中的invoke(Proxy proxy,Method method, object arg[])方法,中处理日志,认证,事务等操作
//接口
public interface Fruit {
void fruitName();
}
//实现类
public class AppleService implements Fruit {
@Override
public void fruitName() {
System.out.println( "我是苹果");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理对象工场
public class ProxyFactory {
private Object targect;
public ProxyFactory(Fruit fruit) {
targect = fruit;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(targect.getClass().getClassLoader(), targect.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理进来了");
Object object = method.invoke(targect, args);
System.out.println("动态代理执行完了");
return object;
}
});
}
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(new AppleService());
Fruit target = (Fruit) proxyFactory.getProxyInstance();
target.fruitName();
}
}
步骤:(1)构造InvocationHandler处理器,定义invoke()方法(2)获取Proxy代理类,并生成代理类对象,调用方法完成相关操作
Proxy.newProxyInstance()
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行,invoke(Proxy proxy,Method method, object arg[])
静态代理:实现了被代理类接口的类,其中保存了一个被代理类的实例。在接口的实现方法中,调用被代理对象对应的方法,同时添加需要的其他操作。缺点:代理类和委托类都实现了同样的接口,代码重复;当需要对对不同的委托类实现相同的处理时,需要定义多个代理类
CGLIB动态代理:无论是静态代理还是动态代理都需要委托类实现接口,如果要对不实现接口的类进行代理,就需要使用cglib库,使用Enhancer来创建代理类,使用MethodIntercepter接口,重写intercept()方法,实现具体操作
//未实现接口
public class BananaService {
public void fruitName() {
System.out.println("我是香蕉");
}
}
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyFactory {
private Object target;
public CglibProxyFactory(BananaService bananaService) {
target = bananaService;
}
public Object getCglibProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib 动态代理进来了");
Object value = method.invoke(target, objects);
System.out.println("cglib 动态代理跑完了");
return value;
}
});
return enhancer.create();
}
public static void main(String[] args) {
CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(new BananaService());
BananaService proxy = (BananaService)cglibProxyFactory.getCglibProxyInstance();
proxy.fruitName();
}
}
Spring会根据具体的Bean是否具有接口去选择动态代理方式,如果有接口,使用的是Jdk的动态代理方式,如果没有接口,使用的是cglib的动态代理方式。
更多推荐
所有评论(0)