本篇博文主要包含:
- 自定义注解
- 内置注解
- JAVA23种设计模式全解析
- 静态代理
- 动态代理
jdk动态代理
cglib动态代理 - CGLIB与JDK动态代理的区别
一、自定义注解
Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。其分为:内置注解(jdk自带)和自定义注解。
-
内置注解
(1) @SuppressWarnings 在程序前面加上可以在javac编译中去除警告–阶段是SOURCE
(2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE
(3)@Overricle 打上这个标记说明该方法是将父类的方法重写–阶段是SOURCE -
自定义注解
元注解的作用就是负责注解其他注解。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
- 代理模式
通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。既(AOP微实现) ,AOP核心技术面向切面编程。
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();
}
}
运行结果:
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();
}
运行结果:
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();
}
运行结果:
1.6 CGLIB与JDK动态代理区别
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换