熟悉注解底层实现原理
完成ORM框架底层原理
常用设计模式
单例、工厂、代理
一.自定义注解
1.1什么是注解?
Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。
注解分类:内置注解(也成为元注解jdk自带注解)、自定义注解(Spring框架)
1.2什么是内置注解
Object类有哪些方法?
1.clone方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedExcepti
2.getClass方法
final方法,获得运行时类型。
3.toString方法
该方法用得比较多,一般子类都有覆盖。
4.finalize方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5.equals方法
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6.hashCode方法
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
7.wait方法
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
8.notify方法
该方法唤醒在该对象上等待的某个线程。
9.notifyAll方法
该方法唤醒在该对象上等待的所有线程。
2 注解的分类
注解按照使用的方式和用途,注解可以分为三大类。
(1)内建注解。
内建注解也称为基本注解,位于java.lang包下。
内建注解有三个:
1,检验重写父类方法:@Override
2,标识方法已经过时:@Deprecated
3,取消编译器警告:@SurppressWarnings
(2)元注解。
元注解就是在注解上添加的注解。
位置:元注解位于java.lang.annotation子包中。
作用:用于修饰其他注解。
元注解有四个:
@Retention,@Target,@Documented,@Inherited。
(3)自定义注解。
需要用到关键字@interface来定义。
比如
(1) @SuppressWarnings 再程序前面加上可以在javac编译中去除警告--阶段是SOURCE
(2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE
(3)@Overricle 打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE
1.1@Overricle 案例演示
@Override public String toString() { returnnull; } |
1.2@Deprecated案例演示
new Date().parse(""); |
1.3 @SuppressWarnings 案例演示
@SuppressWarnings({ "all" }) publicvoid save() { java.util.Listlist = newArrayList(); } |
四个元注解的作用:
@Retention:用来描述被修饰的注解的生命周期。
@Target:用于指定被修饰的注解的适用范围,即被修饰的注解可以用来修饰哪些程序元素。
@Documented:用于指定被修饰的注解将被javadoc工具提取成文档。
@Inherited:用于指定被@Inherited修饰的注解具有继承性。
2.1 单例模式
2.1.1什么是单例模式?
每当new了一个对象,都会在堆内存中会有一个内存地址
单例保证一个对象JVM中只能有一个实例,常见单例懒汉式、饿汉式
什么是懒汉式,就是需要的才会去实例化,线程不安全。
什么是饿汉式,就是当class文件被加载的时候,初始化,天生线程安全。
2.1.2单例写法
懒汉式代码
classSingletonTest {
publicstaticvoid main(String[] args) {
Singleton sl1 = Singleton.getSingleton();
Singleton sl2 = Singleton.getSingleton();
System.out.println(sl1 == sl2);
}
}
publicclass Singleton {
// 当需要的才会被实例化
privatestatic Singleton singleton;
// 将构造函数私有化,防止无限new的问题
private Singleton() {
}
Synchronized public static SingletongetSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
Return singleton;
}
}
饿汉式代码
class SingletonTest1 {
publicstaticvoid main(String[] args) {
Singleton1sl1 = Singleton1.getSingleton();
Singleton1sl2 = Singleton1.getSingleton();
System.out.println((sl1 == sl2)+"-");
}
}
publicclassSingleton1 {
//当class 文件被加载初始化
privatestaticSingleton1singleton = newSingleton1();
private Singleton1() {
}
publicstaticSingleton1getSingleton() {
returnsingleton;
}
}
2.4工厂模式
2.4.1什么是工厂模式?
实现创建者和调用者分离
2.4.2简单工厂代码
publicinterface Car {
publicvoid run();
}
Public class AoDi implements Car {
@Override
publicvoid run() {
System.out.println("奥迪....");
}
}
publicinterface Car {
publicvoid run();
}
Public cclass CarFactory {
staticpublic Car createCar(String carName) {
Car car = null;
if (carName.equals("奥迪")) {
car = newAoDi();
} elseif (carName.equals("奔驰")) {
car = newBenChi();
}
returncar;
}
publicstaticvoid main(String[] args) {
Car car1 = CarFactory.createCar("奥迪");
Car car2 = CarFactory.createCar("奔驰");
car1.run();
car2.run();
}
}
2.4.3工厂方法
publicinterface Car {
publicvoid run();
}
publicclassAoDiimplements Car {
@Override
publicvoid run() {
System.out.println("奥迪....");
}
}
publicclassBenChiimplements Car {
@Override
publicvoid run() {
System.out.println("奔驰....");
}
}
publicclassAoDiChiFactory {
staticpublic Car createCar() {
returnnewAoDi();
}
}
publicinterfaceBenChiFactory {
staticpublic Car createCar() {
returnnewBenChi();
}
}
publicclass Main {
publicstaticvoid main(String[] args) {
Car c1 = AoDiChiFactory.createCar();
Car c2 = BenChiFactory.createCar();
c1.run();
c2.run();
}
}
2.5代理模式
2.5.1什么是代理?
通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。既(AOP微实现) ,AOP核心技术面向切面编程。
2.5.1代理应用场景
安全代理可以屏蔽真实角色
远程代理远程调用代理类RMI
延迟加载先加载轻量级代理类,真正需要在加载真实
2.5.2代理的分类
静态代理(静态定义代理类)
动态代理(动态生成代理类)
Jdk自带动态代理
Cglib、javaassist(字节码操作库)
2.5.3 静态代理
静态代理需要自己生成代理类
publicclassXiaoMingimplements Hose {
@Override
publicvoidmai() {
System.out.println("我是小明,我要买房啦!!!!haha ");
}
}
class Proxy implements Hose {
privateXiaoMingxiaoMing;
public Proxy(XiaoMingxiaoMing) {
this.xiaoMing = xiaoMing;
}
publicvoidmai() {
System.out.println("我是中介看你买房开始啦!");
xiaoMing.mai();
System.out.println("我是中介看你买房结束啦!");
}
publicstaticvoid main(String[] args) {
Hose proxy = new Proxy(newXiaoMing());
proxy.mai();
}
}
2.5.4JDK动态代理(不需要生成代理类)
实现InvocationHandler就可以了。
publicinterface Hose {
/**
*
* @methodDesc: 功能描述:(买房代理)
* @param:
* @createTime:2017年8月27日上午2:54:34
* @returnType: void
*/
publicvoidmai();
}
publicclassXiaoMingimplements Hose {
@Override
publicvoidmai() {
System.out.println("我是小明,我要买房啦!!!!haha ");
}
}
publicclassJDKProxyimplementsInvocationHandler {
private Object tarjet;
publicJDKProxy(Object tarjet) {
this.tarjet = tarjet;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
System.out.println("我是房产中介.....开始监听你买房啦!");
Object oj = method.invoke(tarjet, args);
System.out.println("我是房产中介.....结束监听你买房啦!");
returnoj;
}
}
class Test222 {
publicstaticvoid main(String[] args) {
XiaoMingxiaoMing = newXiaoMing();
JDKProxyjdkProxy = newJDKProxy(xiaoMing);
Hose hose=(Hose) Proxy.newProxyInstance(xiaoMing.getClass().getClassLoader(), xiaoMing.getClass().getInterfaces(), jdkProxy);
hose.mai();
}
}
2.5.6 CGLIB动态代理
实现
importjava.lang.reflect.Method;
importnet.sf.cglib.proxy.Enhancer;
importnet.sf.cglib.proxy.MethodInterceptor;
importnet.sf.cglib.proxy.MethodProxy;
publicclassCglibimplementsMethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxymethodProxy) throwsThrowable {
System.out.println("我是买房中介,开始监听你买房了....");
Object invokeSuper = methodProxy.invokeSuper(o, args);
System.out.println("我是买房中介,开结束你买房了....");
returninvokeSuper;
}
}
class Test22222 {
publicstaticvoid main(String[] args) {
Cglibcglib = newCglib();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(XiaoMing.class);
enhancer.setCallback(cglib);
Hose hose = (Hose) enhancer.create();
hose.mai();
}
}
2.5.7CGLIB与JDK动态代理区别
jdk动态代理是由内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。
注:asm其实就是java字节码控制.