java架构学习——7. 自定义注解与java设计模式

本篇博文主要包含:

  • 自定义注解
  • 内置注解
  • JAVA23种设计模式全解析
  • 静态代理
  • 动态代理
    jdk动态代理
    cglib动态代理
  • CGLIB与JDK动态代理的区别

一、自定义注解
Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。其分为:内置注解(jdk自带)和自定义注解。

  1. 内置注解
    (1) @SuppressWarnings 在程序前面加上可以在javac编译中去除警告–阶段是SOURCE
    (2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE
    (3)@Overricle 打上这个标记说明该方法是将父类的方法重写–阶段是SOURCE

  2. 自定义注解
    元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

  • @Target
    @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
    取值有:
    CONSTRUCTOR:用于描述构造器
    FIELD:用于描述域
    LOCAL_VARIABLE:用于描述局部变量
    METHOD:用于描述方法
    PACKAGE:用于描述包
    PARAMETER:用于描述参数
    TYPE:用于描述类、接口(包括注解类型) 或enum声明
  • @Retention
    表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
    取值有:
    SOURCE:在源文件中有效(即源文件保留)
    CLASS:在class文件中有效(即class保留)
    RUNTIME:在运行时有效(即运行时保留)
  • @Documented
    用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
  • @Inherited
    @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

代码演示:

//定义类注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
	String name() default "";
}

//定义属性注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface property{
	String value() default "";
	int length() default 0;
	String[] arrary() default {};
	
}

@Table(name="one_table")
public class AnnotationDemo {

	@property(value="name",length=2)
	private String name;
	@property(value="age",length=1)
	private String age;
	@property(value="addr", arrary= {"1","2"})
	private String addr;
	
	public static void main(String[] args) throws ClassNotFoundException {
		Class forName = Class.forName("wmq.fly.annotation.AnnotationDemo");
		//获取表名
		Table declaredAnnotation = forName.getDeclaredAnnotation(Table.class);
		//获取注解中name的值
		String tableName = declaredAnnotation.name();
		StringBuffer sb = new StringBuffer("select ");
		//获取当前所有属性
		Field[] declaredFields = forName.getDeclaredFields();
		for(Field field : declaredFields) {
			property declaredAnnotation2 = field.getDeclaredAnnotation(property.class);
			//获取注解中value的值
			String propertyName = declaredAnnotation2.value();
			sb.append(propertyName+", ");
		}
		sb.delete(sb.length()-2, sb.length());
		sb.append(" from "+tableName);
		System.out.println(sb.toString());
	}
}

运行结果:
在这里插入图片描述

二、常用设计模式
JAVA23种设计模式全解析:https://blog.csdn.net/hustwht/article/details/52675325
或 https://blog.csdn.net/zhangerqing/article/details/8194653

  1. 代理模式
    通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。既(AOP微实现) ,AOP核心技术面向切面编程。
    java架构学习——7. 自定义注解与java设计模式_第1张图片

1.1 代理应用场景

  • 安全代理 可以屏蔽真实角色
  • 远程代理 远程调用代理类RMI
  • 延迟加载 先加载轻量级代理类,真正需要在加载真实

1.2 代理的分类

  • 静态代理(静态定义代理类)
  • 动态代理(动态生成代理类)
    Jdk自带动态代理
    Cglib 、javaassist(字节码操作库)

1.3 静态代理
静态代理需要自己生成代理类
代码演示:

//代理对象
class Car{
	
	public void say() {
		System.out.println("汽车行驶中........");
	}
}

//代理类
class ProxyDemo{
	
	private Car car;
	public ProxyDemo(Car car) {
		this.car = car;
	}
	
	public void say() {
		System.out.println("启动喽~~~~~");
		car.say();
		System.out.println("停车哈**********");
	}
}

public class StaticProxyDemo {

	public static void main(String[] args) {
		ProxyDemo proxy = new ProxyDemo(new Car());
		proxy.say();
	}
}

运行结果:
java架构学习——7. 自定义注解与java设计模式_第2张图片

1.4 JDK动态代理(不需要生成代理类)
实现InvocationHandler 就可以了

//代理接口
interface CarInterface{
	public void say();
}
//代理对象
class BMCar implements CarInterface {
	public void say() {
		System.out.println("汽车行驶中........");
	}
}


//JDK动态代理
class JdkProxy implements java.lang.reflect.InvocationHandler{
	private Object ob;
	JdkProxy(Object ob){
		this.ob = ob;
	}
	
	@Override
	public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable {
		System.out.println("启动喽~~~~~");
		Object invoke = paramMethod.invoke(ob, paramArrayOfObject);
		System.out.println("停车哈**********");
		return invoke;
	}
}
public static void main(String[] args) {
		BMCar bMCar = new BMCar();
		JdkProxy jdkProxy = new JdkProxy(bMCar);
		CarInterface car =(CarInterface) Proxy.newProxyInstance(bMCar.getClass().getClassLoader(), bMCar.getClass().getInterfaces(), jdkProxy);
		car.say();
	}

运行结果:
java架构学习——7. 自定义注解与java设计模式_第3张图片

1.5 CGLIB动态代理
代码演示:

class CjlibProxy implements MethodInterceptor {
	@Override
	public Object intercept(Object object, Method methd, Object[] paramArrary, MethodProxy methodProxy) throws Throwable {
		System.out.println("启动喽~~~~~");
		Object invoke = methodProxy.invoke(object, paramArrary);
		System.out.println("停车哈**********");
		return invoke;
	}
}
public static void main(String[] args) {
		Cglib cglib = new Cglib();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(BMCar.class);
		enhancer.setCallback(cglib);
		CarInterface car = (CarInterface) enhancer.create();
		car.say();
	}

运行结果:
java架构学习——7. 自定义注解与java设计模式_第4张图片

1.6 CGLIB与JDK动态代理区别
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  • 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

你可能感兴趣的:(java架构学习)