自定义注解与设计模式

来源:互联网 发布:java实现iis域认证 编辑:程序博客网 时间:2024/06/01 12:31

熟悉注解底层实现原理

完成ORM框架底层原理

常用设计模式

单例、工厂、代理


一.自定义注解

1.1什么是注解?

Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。

注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。

注解分类:内置注解(也成为元注解jdk自带注解)、自定义注解(Spring框架)

1.2什么是内置注解



 Object类有哪些方法?

1.clone方法

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

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 {@Overridepublicvoid 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 {@Overridepublicvoid run() {System.out.println("奥迪....");}}publicclassBenChiimplements Car {@Overridepublicvoid 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 {@Overridepublicvoidmai() {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 {@Overridepublicvoidmai() {System.out.println("我是小明,我要买房啦!!!!haha ");}}publicclassJDKProxyimplementsInvocationHandler {private Object tarjet;publicJDKProxy(Object tarjet) {this.tarjet = tarjet;}@Overridepublic 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 {@Overridepublic 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字节码控制.


原创粉丝点击