一、ApplicationContext
- ApplicationContext被称为Spring上下文,Application Context 是 Spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。
BeanFactory容器
- 这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。BeanFactory 和相关的接口,比如BeanFactoryAware、DisposableBean、InitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。
- 这个接口是Spring中最底层的接口,提供了最简单的容器的功能,只提供了实例化对象和取对象的功能。
- ApplicationContext的重要实现类有两个:ClassPathXmlApplicationContext与FileSystemXmlApplicationContext
- ClassPathXmlApplicationContext:从classpath(resources目录等同于classpath)中读取xml文件加载已经被定义的bean。
- FileSystemXmlApplicationContext:从系统文件中读取xml文件加载已经被定义的bean。
二、动态代理AOP
- AOP(Aspect Oriented Programming)称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题。
- 与AOP有关的两个概念是OOP(面向对象编程)与POP(面向过程编程)。
- AOP的核心技术是代理。
1、动态代理
在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理对象,动态代理可以让我们在不修改源码的情况下增加新的功能。Java的动态代理有两种方式。
- 1、jdk代理方式
- 这种方式要求被代理的类必须实现某个接口,实现原理是利用对象的类的字节码接口,写出一个新的类到本地区,通过编译器直接编译成.class文件,再通过类加载器加载进来。最重要的一步是:
public interface Person<T> {
List<T> get();
boolean save(T s);
boolean delete(int id);
boolean update(T obj);
}
public class Factory {
public static Person get Person(){
Person p = new PersonImpl();//被代理的对象
MyAspect ma = new MyAspect();//需要添加的代理
/**
* @param Factory.class.getClassLoader() 类加载器,用来加载代理类
* @param us.getClass().getInterfaces() 被代理的接口
* @param new InvocationHandler() 内部类 重写invoke方法
*/
Person ps = ( Person) Proxy.newProxyInstance(Factory.class.getClassLoader(), us.getClass().getInterfaces(), new InvocationHandler() {
/**
* 代理对象调用的回掉方法
* @param proxy 代理对象
* @param method 被代理的方法
* @param args 被代理方法的参数列表对象
* @return 每个方法的最终返回值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ma.before();
Object obj = method.invoke(p, args);//原方法
ma.after();
return obj;
}
});
return ps;
}
}
- 2、使用cglib
- 这是非Java原生的动态代理,效率更高,限制更小,而且不需要被代理的类实现接口。
public static void main(String[] args) {
//导入包 cglib-core asm ant ant-launcher
//创建运行器
MethodInterceptor mi = new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("运行前");
arg3.invokeSuper(arg0, arg2);
System.out.println("运行后");
return null;
}
};
//获取代理类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(Demo.class);
//运行任务
enhancer.setCallback(mi);
//创建代理对象
Demo d = (Demo)enhancer.create();
d.method();
}
-
cglib实现动态代理的原理是代理类去继承目标类,然后重写其中目标类的方法,这样每次调用代理类的方法都会被方法拦截器拦截,在拦截器中才调用目标类的该方法。
-
JDK代理方式与cglib代理方式的区别
- JDK代理只能对实现了接口的类生成代理,而CGLIB是通过继承的方式实现代理也可以为实现了接口的类强制使用
- JDK代理在使用次数较少时效率高于CGLIB代理,当大量使用时CGLIB代理更胜一筹.但随着jdk版本的升级,JDK代理效率不断提升,到jdk8时高于CGLIB代理
Spring框架中的动态代理方式
1. 创建被代理类接口并实现接口
2. 创建代理类,并实现MethodInterceptor接口
- 重写invoke方法
@Override public Object invoke(MethodInvocation invocation) throws Throwable { before(); // 业务处理方法的调用 Object obj = invocation.proceed(); after(); return obj; }
3. 配置beans.xml
- 分别配置被代理类bean(id="us")和代理类bean(id="my")
- 配置代理工厂
- ProxyFactoryBean代理的FactoryBean对象 包含四个属性注入:
- interfaces: 接口对象们<list> <value></value> <value></value> </list>
- target:目标对象,哪个对象将被以代理的方式创建
- interceptorNames:拦截对象的名称,自定义的MethodInterceptor对象,注意它的包结构组成
- optimize:boolean类型的值:true:强制使用cglib的动态代理方式;false:使用jdk自带的动态代理;cglib:code generation library,代码生成库,性能更高
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.aop.Service" />
<property name="target" ref="us" />
<property name="interceptorNames" value="my" />
<property name="optimize" value="true" />
</bean>
网友评论