Spring学习03

来源:互联网 发布:amtemu v0.8.1 mac 编辑:程序博客网 时间:2024/05/22 05:33

AOP

Spring两大特性IOC和AOP,IOC通过容器管理对象,AOP提供切面拦截处理。


实现aop两种方法:

1,动态代理:被代理对象必须实现接口

有一个接口及其实现类

public interface UserService {
    void add();

    void delete();

    void find();

    void update();
}

public class UserServiceImp implements UserService {

    @Override
    public void add() {
        System.out.println("add");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }

    @Override
    public void find() {
        System.out.println("find");
    }

    @Override
    public void update() {
        System.out.println("update");
    }
}

然后用一个类去代理:通过传入实现类UserServiceImp,调用getUserService方法,返回的就是附加了功能的实现类

public class UserServiceFactory implements InvocationHandler {
    private UserService us;

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

    public UserService getUserService() {
        UserService us = (UserService) Proxy.newProxyInstance(UserServiceFactory.class.getClassLoader(),
                UserServiceImp.class.getInterfaces(), this);
        return us;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("start!");
        Object obj = method.invoke(us, args);
        System.out.println("submit!");
        return obj;
    }
}

测试类:

public class test {
    // 使用动态代理
    @Test
    public void test() {
        UserServiceImp usi = new UserServiceImp();
        UserServiceFactory factory = new UserServiceFactory(usi);
        UserService us = factory.getUserService();
        us.add();
        us.delete();
    }

}

2,cglib代理:采用的是继承需要代理的类,可代理任何类(除了被final修饰的类,因为不能被继承),代理类方法methodProxy的调用使用索引定位方法位置,比反射速度快

此时UserServiceFactory变一下

public class UserServiceFactory2 implementsMethodInterceptor {
    public UserService getUserService() {
        Enhancer en = new Enhancer();// 生成代理对象
        en.setSuperclass(UserServiceImp.class);// 代理谁
        en.setCallback(this);// 代理要做什么
        UserService us = (UserService) en.create();// 增强版被代理对象(因为是继承,可以向上转)
        return us;
    }

    @Override
    public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy methodproxy) throws Throwable {
        System.out.println("start!");
        Object obj = methodproxy.invokeSuper(arg0, arg2);
        System.out.println("submit!");
        return obj;
    }
}

测试类方法:

@Test
    public void test2() {
        UserServiceFactory2 usf = new UserServiceFactory2();
        UserService us2 = usf.getUserService();
        us2.add();
    }

------------------------------------------------------------------------------------------------------------------

通知

0,导包aspectjweaver.jar

1,配置xml

<!-- 配置目标对象,UserService测试类要用到 -->
<bean name="UserService" class="proxyInterface.UserServiceImp"></bean>
<!-- 配置通知对象,目标对象调用方法前、后,以及产生异常等等,通知对象将调用其方法做相应处理 -->
<bean name="myAdvice" class="com.cl.a_aspect.MyAdvice"></bean>
<!-- 使用注解织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2,通知类MyAdvice

@Aspect // 表示该类是一个通知类
public class MyAdvice {
    //抽取切入表达式(意思就是后面注解里的MyAdvice.action()其实是@Pointcut注解表达式里的方法名,即proxyInterface包下某个实现类的某个方法名
    @Pointcut("execution(* proxyInterface.*ServiceImp.*(..))")
    public void action() {}
    // 前置通知,调用Pointcut注解里的方法前作用
    @Before("MyAdvice.action()")
    public void before() {
        System.out.println("前置通知");
    }

    // 环绕通知,前后都调用
    @Around("MyAdvice.action()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("before");
        pjp.proceed();
        System.out.println("after");
    }

    // 切入点方法之后调用,不管是否有异常
    @After("MyAdvice.action()")
    public void after() {
        System.out.println("不管是否有异常");

    }

    // 后置通知
    @AfterReturning("MyAdvice.action()")
    public void afterReturning() {
        System.out.println("后置通知");
    }

    // 异常拦截通知,出现异常调用
    @AfterThrowing("MyAdvice.action()")
    public void afterException() {
        System.out.println("异常拦截通知");
    }
}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
("classpath:com/cl/AdviceAnnotation/applicationContext.xml")
public class test{
    @Resource(name = "UserService")
    private UserService us;

    @Test
    public void test() {
        us.add();
    }
}

上面2个注解的作用就是创建容器并整合了Junit4,跟new ClassPathXmlApplicationContext(“applicationContext.xml”)是一样