zoukankan      html  css  js  c++  java
  • Java中注解,反射注解,Bean工厂,动态代理

    注解

    注解的定义

    //定义属性
    @interface myAnnotation{
    int age();
    String name();
    }

    注解的使用

    //注解的作用目标
     //一般用在类,方法,构造器,参数,局部变量,前
    @MyAnno1
    public class Demo1 {
        @MyAnno1
        private String name;
        
        @MyAnno1
        public Demo1() {
            
        }
        
        @MyAnno1
        public void fun1() {
            
        }
        
        public void fun2(@MyAnno1 String name) {
            @MyAnno1
            String username = "hello";
        }
    }
    //对于定义了属性的注解的使用
    @MyAnnotation(age=32,name="sma")
    public class demo{
    }

    注解属性的类型

    只能是

    /*
    > 8种基本类型
        > String
        > Enum
        > Class
        > 注解类型
        > 以上类型的一维数组类型
    */

    注解的额外内容

    1.默认值

    @interface MyAnno2 {
        int age() default 100;
        String name();
    }

    使用时,该属性可以不赋值。

    2.value属性。

    注解有一个属性名称可以叫value,使用注解是,可以省略value=

    3.作用范围限定

    在定义注解前加上,比如

    //限定注解MyAnno1只能在类,方法和成员变量前使用
    @Target(value={ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
    @interface MyAnno1 {
        
    }

    4保留策略

    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnno1 {
        
    }

    枚举RetentionPolicy有SOURCE,CLASS,RUNTIME,分别说明注解会保留在其中。

    注意:要反射注解,只有使用RUNTIME。

    反射注解

    //反射泛型
    abstract  class A<T>{
    public A(){
    }
    }
    
    
    class B extentds A<String>{
    }
    
    // 现在在其他某处使用类B,B b=new B(),想知道父类泛型具体是什么类。
    在A的构造函数加入如下代码,具体执行在new B()时进行
    
    Class clazz = this.getClass();//得到子类的类型
    Type type = clazz.getGenericSuperclass();//获取传递给父类参数化类型
    ParameterizedType pType = (ParameterizedType) type;//它就是A<String>
    Type[] types = pType.getActualTypeArguments();//它就是一个Class数组
    Class c = (Class)types[0];//它就是String
    
    //可以连在一起写成
    //        Class c = (Class)((ParameterizedType)this.getClass()
    //                .getGenericSuperclass()).getActualTypeArguments()[0];
    //        
    //        System.out.println(c.getName());

     反射注解

    //对于类A和注解MyAnno1
    @MyAnno1(name="A类", age=1, sex="男")
    class A {
        @MyAnno1(name="fun1方法", age=2, sex="女")
        public void fun1() {
            
        }
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnno1 {
        String name();
        int age();
        String sex();
    }

    分别获取类和方法上的注解

    //获取类A上的注解
    /*
             * 1. 得到作用目标
             */
            Class<A> c = A.class;
            /*
             * 2. 获取指定类型的注解
             */
            MyAnno1 myAnno1 = c.getAnnotation(MyAnno1.class);
            System.out.println(myAnno1.name() + ", " 
                        + myAnno1.age() + ", " + myAnno1.sex());
    
    
    //获取方法上的注解
    /*
             * 1. 得到作用目标
             */
            Class<A> c = A.class;
            Method method = c.getMethod("fun1");
            
            
            /*
             * 2. 获取指定类型的注解
             */
            MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class);
            System.out.println(myAnno1.name() + ", " 
                        + myAnno1.age() + ", " + myAnno1.sex());

    Bean工厂

    先声明若干类和接口

    //以下存在于多个文件
    public class Teacher {
        private String tid;
        private String name;
    .......................
    //getter and setter
    .....
    }
    
    
    public class Student {
        private String number;
        private String name;
        private int age;
        private String sex;
        private Teacher teacher;
        
        public Teacher getTeacher() {
            return teacher;
    //getter and setter
    .....
    }
    
    import cn.itcast.domain.Student;
    
    public interface StudentDao {
        void add(Student stu);
        void update(Student stu);
    }
    
    
    
    public class StudentImpl implements StudentDao {
    
        @Override
        public void add(Student stu) {
            System.out.println("StudentImpl.add()");
        }
    
        @Override
        public void update(Student stu) { 
            System.out.println("StudentImpl.update()");
        }
    
    }
    public class StudentImpl2 implements StudentDao {
    
        @Override
        public void add(Student stu) {
            System.out.println("StudentImp2.add()");
        }
    
        @Override
        public void update(Student stu) { 
            System.out.println("StudentImp2.update()");
        }
    
    }
    public interface StudentService {
        void login();
    }
    
    
    public class StudentServiceImpl implements StudentService {
        private StudentDao studentDao = null;
    
        // 谁调用service方法,谁就需要先调用本方法,提供dao
        public void setStudentDao(StudentDao studentDao) {
            this.studentDao = studentDao;
        }
    
        public void login() {
            studentDao.add(null);
            studentDao.update(null);
        }
    }

     然后在一个xml文件配置这些类的对象

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans>
        <bean id="stu1" className="cn.itcast.domain.Student">
            <property name="number" value="ITCAST_1001"/>
            <property name="name" value="zhangSan"/>
            <property name="age" value="29"/>
            <property name="sex" value="male"/>
            <property name="teacher" ref="t1"/><!-- ref的值必须是另一个been的id -->
        </bean>
        
        <bean id="stu2" className="cn.itcast.domain.Student">
            <property name="number" value="ITCAST_1002"/>
            <property name="name" value="wangWu"/>
            <property name="age" value="94"/>
            <property name="sex" value="female"/>
            <property name="teacher" ref="t1"/><!-- ref的值必须是另一个been的id -->
        </bean>
        
        <bean id="t1" className="cn.itcast.domain.Teacher">
            <property name="tid" value="TEACHER_2001" />
            <property name="name" value="liSi" />
            <property name="salary" value="123.456" />
        </bean>
        
        <bean id="stuDao" className="cn.itcast.dao.impl.StudentImpl2">
        </bean>
        
        <bean id="stuService" className="cn.itcast.service.impl.StudentServiceImpl">
            <property name="studentDao" ref="stuDao"/>
        </bean>
    </beans>

    在需要的时候,从bean.xml中生成对象并使用

    BeanFactory bf = new BeanFactory("beans.xml");
    Student s1 = (Student)bf.getBean("stu1");
    StudentDao stuDao = (StudentDao)bf.getBean("stuDao");
    stuDao.add(null);
    stuDao.update(null);
    StudentService service = (StudentService) bf.getBean("stuService");
    service.login();

    动态代理

    目的:现在有若干个接口,要得到一个对象,这个对象实现了这些接口的方法。

    思考;

    1.这个对象的类名并不重要,我们可以用Object来表示,如果有个Object o这个满足要求的对象,我们可以将其转化成接口类型,

    然后调用接口方法。

    2.接口中的方法由谁来实现?

    这里使用InvocationHandler接口,实现其invoke方法

    public Object invoke(Object proxy,Method m,Object[] args){

    //具体实现

     .....

    }

    这样我们调用我们接口中的方法其实就是调用了invoke里面的内容

    其中Method就是接口中的Method,接口方法的参数会传入args中。

    interface A {
        public void a();
        public void aa();
        public Object aaa(String s, int i);
    }
    
    interface B {
        public void b();
        public void bb();
    }
    
    @Test
        public void fun1() {
            /*
             * 三大参数
             * 1. ClassLoader
             * 方法需要动态生成一个类,这个类实现了A、B接口,然后创建这个类的对象!
             * 需要生成一个类,这个类也需要加载到方法区中,谁来加载,当然是ClassLoader!!!
             * 
             * 2. Class[] interfaces
             * 它是要实现的接口们
             * 
             * 3. InvocationHandler
             * 它是调用处理器
             * 敷衍它!
             * 
             * 代理对象的实现的所有接口中的方法,内容都是调用InvocationHandler的invoke()方法。
             */
            ClassLoader loader = this.getClass().getClassLoader();
            InvocationHandler h = new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    System.out.println("你好,动态代理!");
                    if(args[0]!=null){
                        System.out.println(args[0]);
                    }
                    return "返回的字符串";
                }
            };
            // 使用三大参数创建代理对象!!!
            Object o = Proxy.newProxyInstance(loader, new Class[]{A.class, B.class}, h);
            // 强转成A和B类型,成功了!
            A a = (A) o;
            Object result = a.aaa("hello", 100);
            System.out.println(result);
        }

    控制台输出

    你好,动态代理!
    hello
    返回的字符串

     动态代理的应用1:增强

    // 服务员
    public interface Waiter {
        // 服务
        public void serve();
    }
    public class ManWaiter implements Waiter {
        public void serve() {
            System.out.println("服务中...");
        }
    }
    public class Demo2 {
        @Test
        public void fun1() {
            Waiter manWaiter = new ManWaiter();//目标对象
            /*
             * 给出三个参数,来创建方法,得到代理对象
             */
            ClassLoader loader = this.getClass().getClassLoader();
            Class[] interfaces = {Waiter.class};
            InvocationHandler h = new WaiterInvocationHandler(manWaiter);//参数manWaiter表示目标对象
            // 得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象!
            Waiter waiterProxy = (Waiter)Proxy.newProxyInstance(loader, interfaces, h);
            
            waiterProxy.serve();//前面添加“您好”, 后面添加“再见”
        }
    }
    
    class WaiterInvocationHandler implements InvocationHandler {
        private Waiter waiter;//目标对象
        
        public WaiterInvocationHandler(Waiter waiter) {
            this.waiter = waiter;
        }
        
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("您好!");
            this.waiter.serve();//调用目标对象的目标方法
            System.out.println("再见!");
            return null;
        }
    }

     例子2:增强

    public interface Waiter {
        // 服务
        public void serve();
        
        public void shouQian();
    }
    public class ManWaiter implements Waiter {
        public void serve() {
            System.out.println("服务中...");
        }
        
        public void shouQian() {
            System.out.println("收钱!");
        }
    }
    public interface AfterAdvice {
        public void after();
    }
    public interface BeforeAdvice {
        public void before();
    }
    
    
    public class Demo3 {
        @Test
        public void fun1() {
            ProxyFactory factory = new ProxyFactory();//创建工厂
            factory.setTargetObject(new ManWaiter());//设置目标对象
            factory.setBeforeAdvice(new BeforeAdvice() {//设置前置增强
                public void before() {
                    System.out.println("您好不好!");
                }
            });
            
            factory.setAfterAdvice(new AfterAdvice() {//设置后置增强
                public void after() {
                    System.out.println("再见不见!");
                }
            });
            
            Waiter waiter = (Waiter)factory.createProxy();
            waiter.shouQian();
        }
        }
    
    public class ProxyFactory {
        private Object targetObject;//目标对象
        private BeforeAdvice beforeAdvice;//前置增强
        private AfterAdvice afterAdvice;//后置增强
        
        
        /**
         * 用来生成代理对象
         * @return
         */
        public Object createProxy() {
            /*
             * 1. 给出三大参数
             */
            ClassLoader loader = this.getClass().getClassLoader();
            Class[] interfaces = targetObject.getClass().getInterfaces();
            InvocationHandler h = new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    /*
                     * 在调用代理对象的方法时会执行这里的内容
                     */
                    // 执行前置增强
                    if(beforeAdvice != null) {
                        beforeAdvice.before();
                    }
                    
                    Object result = method.invoke(targetObject, args);//执行目标对象的目标方法
                    // 执行后置增强
                    if(afterAdvice != null) {
                        afterAdvice.after();
                    }
                    
                    // 返回目标对象的返回值
                    return result;
                }
            };
            /*
             * 2. 得到代理对象
             */
            Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
            return proxyObject;
        }
        
        
        public Object getTargetObject() {
            return targetObject;
        }
        public void setTargetObject(Object targetObject) {
            this.targetObject = targetObject;
        }
        public BeforeAdvice getBeforeAdvice() {
            return beforeAdvice;
        }
        public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
            this.beforeAdvice = beforeAdvice;
        }
        public AfterAdvice getAfterAdvice() {
            return afterAdvice;
        }
        public void setAfterAdvice(AfterAdvice afterAdvice) {
            this.afterAdvice = afterAdvice;
        }
    }
    View Code
  • 相关阅读:
    JqueryValidate表单相同Name不校验问题解决
    钉钉SDK使用。
    禁用software reporter tool.exe 解决CPU高占用率的问题
    一个小巧,也很nice的“小日历”--一个Android App
    Android模拟器太慢怎么办?使用微软的VS模拟器
    windows10下录屏
    启明星会议室预订系统(企业微信)版发布
    JS图片压缩
    JS操作摄像头
    钉钉版会议室预订系统使用指南
  • 原文地址:https://www.cnblogs.com/legion/p/9443921.html
Copyright © 2011-2022 走看看