目录
1、控制反转(IOC)
1.1、实现原理(流程):(反射+XML技术)
1.2、IOC的好处
1.3、IOC类型
1.4、IOC的初始化过程
1.5、拓展:反射和new
2、AOP(面向切面编程)
2.1、AOP的应用场景
2.2、AOP基本术语切点、切面、连接点、通知等
2.3、AOP的两种实现方式(注解、xml文件)
2.3.1、XML方式
2.3.2、注解方式
2.4、AOP原理(动态代理)
2.4.1、JDK(动态)代理(反射)
2.4.2、cglib代理
2.5、Spring默认动态代理
将创建管理对象的工作交给容器来做。在容器初始化(或在某个时间节点)通过反射机制创建好对象,在使用时直接从容器中获取。
利用(反射+工厂)技术,根据配置文件中给出的类名生成相应的对象。
Class.forName(className).newInstance。
创建Bean及其依赖对象的工作交给IOC容器管理,业务代码只需要getBean就行了。将依赖关系写入配置文件中,有修改时,直接修改配置文件即可,而不用去业务代码中每一个使用Bean的地方修改。
资源定位、资源载入BeanDefinition、
a、Resource定位(Bean的定义文件定位),返回Resource对象
Resource对象与对应ApplicationContext类型如下:
FileSystemResource(绝对路径定位):FileSystemXmlApplicationContext;
ClassPathResourcee(类路径定位):ClassPathXmlApplicationContext;
ServletContextResource(web应用根目录):XmlWebApplicationContext;
UrlResource:访问网络资源的实现类。例如file: http: ftp:等前缀的资源对象;
ByteArrayResource: 访问字节数组资源的实现类。
@Configuation:AnnotationConfigApplicationContext
Spring提供ResourceLoader接口用于实现不同的Resource加载策略,所有的ApplicationContext均实现了ResourceLoader。
b、将Resource定位好的资源载入到BeanDefinition
加载Resource对象中的Bean配置成BeanDefinition,如果Bean有依赖关系,则使用占位符(getBean时,将占位符替换成相应的Bean)暂时代替。
c、将
将一些系统性相关(日志、事务、安全)的编程工作,独立提取出来,独立实现,作为一个公共切面切入到相关的业务逻辑中。
将业务逻辑代码与公共功能代码分离开,使开发人员能更专注地编写业务逻辑代码。
在不改变业务逻辑代码的前提下,在业务逻辑之前、之后、或者周围添加横切关注点(切面),对目标功能进行扩展。
事务(数据库更新),权限(web请求权限),日志(每一次更新记录)等。
普通工程通过new ClassPathXmlApplicationContext("applicationContext.xml")初始化Spring。
在执行DogService类中的方法时,执行前会先执行PointCutXmlConf类中的beforeAdvice方法,执行后会执行PointCutXmlConf类中的afterAdvice方法。
利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
动态代理实际上是程序在运行中,根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程。
而动态生成的代理类已经继承了Proxy类,由于Java的单继承,所以只能靠实现被代理类的接口的形式,而不是靠继承被代理类的形式。
JVM编译完成时并没有实际的字节码文件,而是在运行时动态生成类字节码,并加载到JVM中。
优点:通过反射,可以有效减少代理类的数量,使用更灵活;
缺点:反射代理,比较消耗系统性能。
目标对象实现接口,代理对象可以不实现业务接口。
主要类:
Java.lang.reflect.Proxy以及Java.lang.reflect. InvocationHandler接口(事件处理器)
Proxy类:创建一个代理对象
InvocationHandler接口:代理实例的调用处理程序。
主要方法:
JDK代理类实例:
public class JingJiPenple{
//维护一个目标对象
private Object target;
public JingJiPenple(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理---我是经纪人,我替明星接下这个演出");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("动态代理---我是经纪人,明星演出结束");
return returnValue;
}
}
);
}
}
也可以把InvocationHandler独立出来:
public static void main(String[] args) {
IActor star = new StarPeople();
// 给目标对象,创建代理对象
IActor proxy = (IActor) Proxy.newProxyInstance(star.getClass().getClassLoader(),
star.getClass().getInterfaces(), new MyInvocaionHandler(star));
proxy.sing();
proxy.dance();
}
class MyInvocaionHandler implements InvocationHandler{
private Object object;
public MyInvocaionHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理前置操作");
Object returnValue = method.invoke(object, args);
System.out.println("动态代理后置操作");
return returnValue;
}
}
利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
由于被代理类没有实现接口,所以运行时在内存中动态生成一个子类对象从而实现对目标对象的扩展。子类对象会重写目标对象的方法,所以目标对象不能为final类。
代理类和目标类都无需实现业务接口。
public class JingJiPenple implements MethodInterceptor{
Object target;
public JingJiPenple(Object target){
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//工具类
Enhancer en = new Enhancer();
//设置父类
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback((Callback) this);;
//创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("Cglib代理---我是经纪人,我代明星接下演出!!!");
//执行目标对象的方法
Object returnValue = method.invoke(target, arg2);
System.out.println("Cglib代理---我是经纪人,明星演出结束!!!");
return returnValue;
}
}
Spring在5.X之前默认的动态代理实现一直是jdk动态代理。但是从5.X开始,Spring就开始默认使用Cglib来作为动态代理实现。
SpringBoot从2.X开始也转向了Cglib动态代理实现。
JDK动态代理要求接口,没有接口的情况下会报错。
而CGLIB作为默认动态代理,效果和JDK差不多,但是不会报错,更方便。
以上内容为个人学习汇总,仅供学习参考,如有问题,欢迎在评论区指出,谢谢!