发表于: 2017-12-06 23:17:13
1 671
今日完成的事情:
今天进行了复盘评审,施星大佬提问的几个问题没有很好的回答上来,总体来说还是对敏捷开发流程不熟悉。
然后今天学习了一波AOP
从单纯的Java代理到Spring AOP面向切面都了解了一下:
只用Java代理实现:
首先是接口和实现类,就是我们的主页务:
public interface Greeting {
public void sayHello(String name);
}
public class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
System.out.println("Hello:"+name);
}
然后就是代理:
public class GreeetingBeforeAndAfterAdvice implements MethodBeforeAdvice,AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("After");
}
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("Before");
}
}
这种方式是纯Java的,要实现Java提供的MethodBeforeAdvice等几种方法。
这就是代理实现对主页务的逻辑进行增强。
然后用单元测试进行测试:
@Test
public void client1(){
ProxyFactory proxyFactory=new ProxyFactory();
proxyFactory.setTarget(new GreetingImpl());
proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice());
Greeting greeting=(Greeting)proxyFactory.getProxy();
greeting.sayHello("jack");
}
需要代理工厂,设置target,就是代理对象,还有advice,就是增强逻辑。
运行结果:
由于后面的运行结果和上面基本一样,基本上就是实现增强的逻辑不一样,我就不粘贴重复的运行结果了。
然后Java方式实现环绕增强:
public class GreetAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
before();
Object result=methodInvocation.proceed();
after();
return result;
}
public void before(){
System.out.println("Before");
}
public void after(){
System.out.println("After");
}
}
首先实现MethodInterceptor,然后就是增强的业务逻辑。
单元测试:
@Test
public void client1(){
ProxyFactory proxyFactory=new ProxyFactory();
proxyFactory.setTarget(new GreetingImpl());
proxyFactory.addAdvice(new GreetAroundAdvice());
Greeting greeting=(Greeting)proxyFactory.getProxy();
greeting.sayHello("jack");
}
和上面差不多,需要更改的地方是增强的业务,就是addAdvice。
接下来是声明式增强,在spring配置文件中进行配置:
<context:component-scan base-package="com.mmy.*"/>
<!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
<bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.mmy.service.Greeting"/>
<property name="target" ref="greetingImpl"/>
<property name="interceptorNames" value="greetAroundAdvice"/>
</bean>
就是把上面的增强业务配置称为一个bean。
需要在增强类和主页务类上面加上注解:
@Component
public class GreetingImpl implements Greeting {
@Component
public class GreetAroundAdvice implements MethodInterceptor {
@Override
然后就是单元测试:
从 Context 中根据 id 获取 Bean 对象(其实就是一个代理),调用代理的方法。
@Test
public void client2(){
ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");
Greeting greeting= (Greeting) context.getBean("greetingProxy");
greeting.sayHello("tom");
}
把创建代理工厂之类的事情就交给spring来实现了。
引入增强:
上面的都是都方法进行增强,引入增强是对类进行增强:
定义一个新的接口:
public interface Love {
public void display(String name);
}
定义授权引入增强类:
定义一个授权引入增强类,实现Love接口,用以丰富GreetingImpl类的功能,这样GreetingImpl就能很巧妙的使用Love接口里的方法而不用去implement。
@Component
public class LoveAdvice extends DelegatingIntroductionInterceptor implements Love {
@Override
public void display(String name) {
System.out.println("You are my heart:"+name);
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return super.invoke(invocation);
}
要继承上面那个一大串东西。
spring配置:
<bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.mmy.service.Love"/>
<property name="target" ref="greetingImpl"/>
<property name="interceptorNames" value="loveAdvice"/>
<property name="proxyTargetClass" value="true"/>
</bean>
这里注意proxyTargetClass要设置为true,开始动态代理。
单元测试:
@Test
public void client3(){
ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");
GreetingImpl greeting= (GreetingImpl) context.getBean("greetingProxy");
greeting.sayHello("jack");
// greeting.goodMorning("jack");
Love love=(Love)greeting;
love.display("jack");
}
注意:这里的Love love = (Love)greeting 是将目标类强制向上转型为Love接口,这就是引入增强(DelegatingIntroductionInterceptor)的特性--“接口动态实现”功能。所以display()方法可以由GreetingImpl的对象来调用,只需要强制转换接口就行。
运行结果:
接下来就是面向切面编程,面向切面编程等到明天小课堂之后一块做总结:
今天先总结一下:
AOP是什么:
在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加。AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。
上面介绍的几种方式都是用Java的方式实现了AOP,没有用到Spring。
Spring AOP和Spring结合可以更加优雅的实现面向切面编程。
明日计划的事情:
进行小课堂,老大要来,小课堂要准备的充分一点。
遇到的问题:
Java原生的面向切面编程刚开始理解的时候有一点困惑,真正使用的时候发现和Spring的基本原理差不多。
收获:
对纯java实现AOP进行了了解和简单的demo。
评论