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

 

posted on 2018-08-08 16:58  legion  阅读(421)  评论(0编辑  收藏  举报

导航