Spring学习记录(二)

1.Spring中的AOP思想

aop思想:横向重复,纵向抽取。

AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(Aspect),通知(Advice),连接点(joinpoint),

实现方式就是通过目标对象的代理在连接点前后加入通知,完成统一的切面操作。

这个思想在filter过滤器,拦截器,动态代理中就已经使用过,例如:

(1) 在解决乱码的问题上

(2) 在动态代理上,管理事务:(Proxy.newProxyInstance(Classloader cloader,Interface[] arr, InvocationHandle h))

(3) 拦截器中在参数赋值上,一般每个action的参数赋值,都需要有这个参数,但是有拦截器可以完成把参数赋值到action中,或者校验登录

 2.AOP实现原理

Spring能够为容器中管理的对象生成动态代理对象。

以前未使用Spring时,要使用动态代理,我们需要自己调用这个方法:

Proxy.newProxyInstance(Classloader cloader,Interface[] arr, InvocationHandle h),生成代理对象。

使用Spring后,能帮助我们生成代理对象(只需要在配置文件中配置,或者注解配置即可),那么为什么与AOP思想有关呢?

比如上面例子中的管理事务,使用动态代理对象在进行事务的管理,只需要写一次代码就能够完成,但是需要自己手写代理对象,而用Spring可以自动的生成Service的代理对象,所以称为Spring的AOP思想

所以根据上面的铺垫,AOP的实现原理可以说就是动态代理,或者cglib代理,还有静态织入(引入特定的语法创建“方面”,从而是的编译器可以在编译期间织入有关“方面”的代码)。 ()

(1) 动态代理(优先):被代理对象必须要实现接口,才能产生代理对象,如果没有借口将不能使用动态代理技术

(2) cglib代理(没有接口):第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理。如果目标对象被final修饰,那么该类无法被cglib代理。

 使用动态代理的一个代码示例:

首先创建接口,以及实现类

/**
 * Created by YuKai Fan on 2018/9/27.
 */
public interface UserService {
    void save();
    void delete();
    void update();
    void find();
}
/**
 * Created by YuKai Fan on 2018/9/27.
 */
public class UserServiceImpl implements UserService {
    //这些方法都是业务逻辑,一般来说在进行业务方法进行事务管理
    @Override
    public void save() {
        //如果不使用动态代理每个方法都需要进行打开事务,提交事务的操作
        //System.out.println("打开事务");
        System.out.println("保存用户");
        //System.out.println("提交事务");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void update() {
        System.out.println("修改用户");
    }

    @Override
    public void find() {
        System.out.println("查找用户");
    }
}

再创建一个代理工厂,来生成上面接口的一个代理对象

/**
 * 用户service层的代理工厂
 * Created by YuKai Fan on 2018/9/27.
 */
public class UserServiceProxyFactory implements InvocationHandler{

    private UserService us;

    public UserServiceProxyFactory(UserService us) {
        super();
        this.us = us;
    }

    public UserService getUserServiceProxy() {
        //生成动态代理
        UserService usProxy  = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
                UserServiceImpl.class.getInterfaces(), this);//第三个参数,必须要实现InvocationHandler接口

        return usProxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //使用动态代理,只需要写一次即可
        System.out.println("打开事务");
        Object invoke = method.invoke(us, args);//方法的执行,需要方法所存在的对象,所以需要有实例。创建一个构造方法,来传递一个执行方法所对应的实例对象
        System.out.println("提交事务");
        return invoke;
    }
}

测试:

/**
 * Created by YuKai Fan on 2018/9/27.
 */
public class Demo {
    public static void main(String[] args) {
        UserService us = new UserServiceImpl();
        UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
        UserService usProxy = factory.getUserServiceProxy();
        usProxy.save();
    }
}

测试结果:代理对象每次在执行业务逻辑代码时,都需要执行事务的操作,因为在代理对象在执行方法时,先进行了事务操作。

猜你喜欢

转载自www.cnblogs.com/FanJava/p/9714777.html