spring AOP中,可以通过annotation来简化XML上的配置,可以很灵活的使切面切入到自己想要的方法上,而不需要象aop:config里一定要切入到特定命名方法上
使用annotation来表示pointcut,需要在xml里配置org.springframework.aop.support.annotation.AnnotationMatchingPointcut,
如:<bean name="timeoutPointcut"
class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
<constructor-arg index="0"
value="com.hengtian.fxfundsystem.aop.annotation.UseAOPAnnotation">
</constructor-arg>
<constructor-arg index="1"
value="com.hengtian.fxfundsystem.aop.annotation.TimeoutAnnotation" />
</bean>
第一个参数是标在目标类上的annotation,第二天参数是标注在方法上的Annotation
因此,首先要在自己的工程里定义2个annotation,一个为TimeoutAnnotation,一个为UseAOPAnnotation
@Target({ElementType.TYPE })//表示类标注
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface UseAOPAnnotation {
}
@Target({ElementType.METHOD})//表示方法标注
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeoutAnnotation {
/**
* 默认值(-1):表示不启用超时
*/
public static final long DefaultValue = -1;
/**
* 超时时间,单位是ms
*
* @return
*/
long value() default DefaultValue;
}
在需要AOP的类上使用
@UseAOPAnnotation
@Component("StrongDuck")
public class StrongDuck {
@TimeoutAnnotation(70000)
public void say(){
System.out.println("I am a strong duck");
}
}
timeout通知:
public class TimeoutAdvice implements MethodInterceptor {
/*
* (non-Javadoc)
*
* @see
* org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept
* .MethodInvocation)
*/
public Object invoke(final MethodInvocation methodInvocation)
throws Throwable {
Method targetMethod = methodInvocation.getMethod();
TimeoutAnnotation timeoutAnnotation = targetMethod
.getAnnotation(TimeoutAnnotation.class);
if (timeoutAnnotation != null) {
long waitTime = timeoutAnnotation.value();
if (waitTime != TimeoutAnnotation.DefaultValue) {
Future<?> task = ThreadManager.ExecutorService
.submit(encapsulateSyncToAsync(methodInvocation));
return getAsyncResult(waitTime, task);
}
}
return methodInvocation.proceed();
}
XML中配置拦截器:
<bean id="timeoutInterceptor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="timeoutAdvice" />
<property name="pointcut" ref="timeoutPointcut" />
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass"><!-- 基于类的代理 -->
<value>true</value>
</property>
</bean>
这样,spring就会为你生成aop代理类实现AOP
start with .... connect by prior.....,如果prior缺省,则只能查询符合条件的起始行,并不能递归
从root到末梢:select * from permissiontable t start with parentid=1 connect by prior id=parentid
从末梢到root:select * from permissiontable t start with id=32 connect by prior parentid=id
oracle中有rownum伪列,select rownum from t where rownum<3;表示取整个结果集的前2条记录
当时如果要取分组后每个组里的前几条记录,则rownum无法实现,必须使用oracle里的分析函数,比如row_number()over(partition by 分组字段 order by 排序字段),实现分组后编号
select s.*
from (select row_number() over(partition by p.trader order by p.branch) rn,p.*
from spotdeal p) s
where s.rn < 3
JMM,顾名思义,java memory model。他有3个特征:原子性,可见性,有序性。
JVM系统中都有个一主存,JAVA中所有变量都是存储在主存中,对所有线程都是共享的。
而每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的值,线程对所有变量的修改都是在工作内存中进行,线程之间无法直接互相访问,变量的传递都是通过主存完成。
可见性:JMM中并发线程修改变量,必须将工作内存中的变量同步到主存后,其他线程才能访问到
有续性:通过JAVA提供的同步机制或者volatile关键字 来保证内存的有序性
JAVA中保证多核系统JMM缓存一致性原则:happens-before ordering(先行发生排序)
JAVA提供了
1.synchronized关键字
2.volatile关键字
3.final关键字
4.同步包中的locks
5.同步包中的原子类
JDK代理以前性能不怎么样,但1.6版本却有很大提升
/**
* 行为接口
*
* @author Administrator
*
*/
public interface Study {
public void doStudy();
}
/**
* 目标对象
*
* @author Administrator
*
*/
public class StudyImpl implements Study {
@Override
public void doStudy() {
System.out.println("study jdk proxy");
}
}
/**
* 代理类
* @author Administrator
*
*/
public class JDKProxy implements InvocationHandler {
private Study s;
public JDKProxy(Study s) {
this.s = s;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before jdkproxy");
method.invoke(s, args);
System.out.println("after jdkproxy");
return null;
}
}
应用中进行调用:
public class Test {
public static void main(String[] args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class clazz = StudyImpl.class;//获取目标类的Class对象
Study st = new StudyImpl();//实例化一个目标类
Class proxClass = Proxy.getProxyClass(clazz.getClassLoader(), clazz
.getInterfaces());//通过Proxy静态方法,获取一个于目标类实现同样接口的Class对象,也可以说是兄弟类
Constructor c = proxClass
.getConstructor(new Class[] { InvocationHandler.class });//给这个类一个指定的公开的构造方法
Study ds = (Study) c.newInstance(new Object[] { new JDKProxy(st) });//实例化一个代理类
}
}
最近在学着总结,因为常感觉做完东西,长久不用,过段时间就忘,下次想复习下都不行。
AOP,面向方面编程,我们系统中有很多组件组成,每一个组件负责一部分业务功能,
但是这些组件往往又带有一部分核心功能外的附加功能,而且是重复代码,如:日志,安全,事务! 通过AOP,实现这些附加功能的可重复利用。
AOP其实可以看作是代理模式的扩展,写一个简单的代理
public class ProxySubject implements ProxyInterface {
private Subject innerObj;// 真正的对象
@Override
public void handle() {
innerObj = new Subject();
// 做额外的事情
innerObj.handle();// 真正的处理业务
// 做额外的事情
}
}
Aop中叫代理类为advice,可以有多个连接起来,一个事件链
实现AOP,还需要涉及到JAVA的反射,通过反射,获取method对象,并执行方法,AOP规范包里有个接口
public interface MethodInterceptor extends Interceptor {
*Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
*
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link
* Joinpoint#proceed()}, might be intercepted by the
* interceptor.
*
* @throws Throwable if the interceptors or the
* target-object throws an exception.
Object invoke(MethodInvocation invocation) throws Throwable;
}
通过 MethodInvocation的 getMethod()获得方法对象,并执行
这样,如果你一个类中有很多方法,就可以通过这么一个
AOP中生成代理类有3种方式,
1.静态编译时期,源代码生成,为每个符合条件的类生成一个代理类
2.静态字节码增强通过ASM/CGLIB分析字节码,生成代理类
3.动态字节码增强,spring aop就是这样,ASM/CGLIB或者JDK的动态代理
AOP的原理可以理解为代理模式+放射+自动字节码生成
Spring中动态代理有2种方式,一种是通过CGLIB,一种是JDK。
什么时候采用JDK什么时候采用CGLIB动态生成,主要取决于你又没实现接口,JDK动态代理需要目标类实现某接口,而CGLIB则是生成目标类的子类
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
这个是DefaultAopProxyFactory里创建代理类的方法
jps:查看JAVA线程ID
jinof:
jinfo -flag MaxPermSize <PID> 查看VM参数信息
jstat;
jstat -opt <PID> 一般常用-gcutil查看垃圾收集信息,后面还可加一个间隔时间
jmap:
dump的生成工具,生成堆转储文件后可用MAT分析 jmap -dump:format=b,file=XX <pid>
也可用jmap -histo <PID>将信息输出到控制台
jconsole:
jconsol是jdk自带的一个内存分析工具,它提供了图形界面。可以查看到被监控的jvm的内存信息,线程信息,类加载信息,MBean信息
jdk1.6提供了java visualVM,功能很全,类似Jprofiler
-XX:+HeapDumpOnOutOfMemoryError:这个参数指定在OOM时产生DUMP
-XX:HeapDumpPath 这个是要保存的 dump文件的路径,后缀为.hprof
例子:-XX:HeapDumpPath=C:\Documents and Settings\aoxianglin\Application Data\.visualvm\6u18\var\log\heapdump.hprof