美文网首页
ApplicationContext与Spring AOP实现(

ApplicationContext与Spring AOP实现(

作者: 低调的灬攻城狮 | 来源:发表于2020-02-28 01:24 被阅读0次

一、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对象 包含四个属性注入:
      1. interfaces: 接口对象们<list> <value></value> <value></value> </list>
      1. target:目标对象,哪个对象将被以代理的方式创建
      1. interceptorNames:拦截对象的名称,自定义的MethodInterceptor对象,注意它的包结构组成
      1. 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>

相关文章

网友评论

      本文标题:ApplicationContext与Spring AOP实现(

      本文链接:https://www.haomeiwen.com/subject/bjethhtx.html