java注解实现代码注入 java注解编程

java注解是怎么实现的

java 注解大致分为2类

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:国际域名空间、雅安服务器托管、营销软件、网站建设、普洱网站维护、网站推广。

运行时注解

编译期注解

运行时注解,主要通过反射获取注解信息,在执行你想执行的代码

编译期注解,在编译的时候,就已经处理过,运行的时候不会在处理,编译期注解实现需要实现系统的注解处理器。就是说在java代码编译的时候,生成一个新的类。

spring 注解注入怎么注入属性

1. 使用Spring注解来注入属性

1.1. 使用注解以前我们是怎样注入属性的

类的实现:

Java代码

public class UserManagerImpl implements UserManager {

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

...

}

[java] view plain copy

public class UserManagerImpl implements UserManager {

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

...

}

配置文件:

Java代码

bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl"

property name="userDao" ref="userDao" /

/bean

bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl"

property name="sessionFactory" ref="mySessionFactory" /

/bean

[java] view plain copy

bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl"

property name="userDao" ref="userDao" /

/bean

bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl"

property name="sessionFactory" ref="mySessionFactory" /

/bean

1.2. 引入@Autowired注解(不推荐使用,建议使用@Resource)

类的实现(对成员变量进行标注)

Java代码

public class UserManagerImpl implements UserManager {

@Autowired

private UserDao userDao;

...

}

[java] view plain copy

public class UserManagerImpl implements UserManager {

@Autowired

private UserDao userDao;

...

}

或者(对方法进行标注)

Java代码

public class UserManagerImpl implements UserManager {

private UserDao userDao;

@Autowired

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

...

}

[java] view plain copy

public class UserManagerImpl implements UserManager {

private UserDao userDao;

@Autowired

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

...

}

配置文件

Java代码

bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" /

bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl"

property name="sessionFactory" ref="mySessionFactory" /

/bean

[java] view plain copy

bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" /

bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl"

property name="sessionFactory" ref="mySessionFactory" /

/bean

@Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。以上两种不同实现方式中,@Autowired的标

注位置不同,它们都会在Spring在初始化userManagerImpl这个bean时,自动装配userDao这个属性,区别是:第一种实现

中,Spring会直接将UserDao类型的唯一一个bean赋值给userDao这个成员变量;第二种实现中,Spring会调用

setUserDao方法来将UserDao类型的唯一一个bean装配到userDao这个属性。

1.3. 让@Autowired工作起来

要使@Autowired能够工作,还需要在配置文件中加入以下代码

Java代码

bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /

[java] view plain copy

bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /

1.4. @Qualifier

@Autowired是根据类型进行自动装配的。在上面的例子中,如果当Spring上

下文中存在不止一个UserDao类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在

UserDao类型的bean,也会抛出BeanCreationException异常。我们可以使用@Qualifier配合@Autowired来

解决这些问题。

1. 可能存在多个UserDao实例

Java代码

@Autowired

public void setUserDao(@Qualifier("userDao") UserDao userDao) {

this.userDao = userDao;

}

[java] view plain copy

@Autowired

public void setUserDao(@Qualifier("userDao") UserDao userDao) {

this.userDao = userDao;

}

这样,Spring会找到id为userDao的bean进行装配。

2. 可能不存在UserDao实例

Java代码

@Autowired(required = false)

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

[java] view plain copy

@Autowired(required = false)

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

1.5. @Resource(JSR-250标准注解,推荐使用它来代替Spring专有的@Autowired注解)

Spring 不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。

@Resource

的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName自动注入罢了。

@Resource有两个属性是比较重要的,分别是name和type,Spring将@Resource注解的name属性解析为bean的名字,而

type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策

略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Resource装配顺序

如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(见2);如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配;

1.6. @PostConstruct(JSR-250)

在方法上加上注解@PostConstruct,这个方法就会在Bean初始化之后被Spring容器执行(注:Bean初始化包括,实例化Bean,并装配Bean的属性(依赖注入))。

它的一个典型的应用场景是,当你需要往Bean里注入一个其父类中定义的属性,而你又无法复写父类的属性或属性的setter方法时,如:

Java代码

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

private SessionFactory mySessionFacotry;

@Resource

public void setMySessionFacotry(SessionFactory sessionFacotry) {

this.mySessionFacotry = sessionFacotry;

}

@PostConstruct

public void injectSessionFactory() {

super.setSessionFactory(mySessionFacotry);

}

...

}

[java] view plain copy

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

private SessionFactory mySessionFacotry;

@Resource

public void setMySessionFacotry(SessionFactory sessionFacotry) {

this.mySessionFacotry = sessionFacotry;

}

@PostConstruct

public void injectSessionFactory() {

super.setSessionFactory(mySessionFacotry);

}

...

}

这里通过@PostConstruct,为UserDaoImpl的父类里定义的一个sessionFactory私有属性,注入了我们自

己定义的sessionFactory(父类的setSessionFactory方法为final,不可复写),之后我们就可以通过调用

super.getSessionFactory()来访问该属性了。

1.7. @PreDestroy(JSR-250)

在方法上加上注解@PreDestroy,这个方法就会在Bean初始化之后被Spring容器执行。由于我们当前还没有需要用到它的场景,这里不不去演示。其用法同@PostConstruct。

1.8. 使用context:annotation-config /简化配置

Spring2.1

添加了一个新的context的Schema命名空间,该命名空间对注释驱动、属性文件引入、加载期织入等功能提供了便捷的配置。我们知道注释本身是不会

做任何事情的,它仅提供元数据信息。要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作起来。

AutowiredAnnotationBeanPostProcessor

和CommonAnnotationBeanPostProcessor就是处理这些注释元数据的处理器。但是直接在Spring配置文件中定义这些

Bean显得比较笨拙。Spring为我们提供了一种方便的注册这些BeanPostProcessor的方式,这就

是context:annotation-config /:

Java代码

beans xmlns="" xmlns:xsi="" xmlns:context=""

xsi:schemaLocation="

"

context:annotation-config /

/beans

[java] view plain copy

beans xmlns="" xmlns:xsi="" xmlns:context=""

xsi:schemaLocation="

"

context:annotation-config /

/beans

context:annotationconfig

/将隐式地向Spring容器注册AutowiredAnnotationBeanPostProcessor、

CommonAnnotationBeanPostProcessor、

PersistenceAnnotationBeanPostProcessor以及

RequiredAnnotationBeanPostProcessor这4个BeanPostProcessor。

java注解如何实现 spring 的数组的定义和注入

@Resource(name="myarray")

String[] arrayData;

在配置文件里这样定义

util:list id="myarray"

valuehhhh/value

valuekkkk/value

valueoooo/value

/util:list

注意引入namingspace

xmlns:util="" xsi:schemaLocation=" ”

如何利用Java实现资源注入

Java的功能强大,今儿博洋教育将给大家介绍。 需求:一个应用有两个数据库,分别为DB-A,DB-B。 假设持久层框架使用iBatis来实现,那么SqlMapClient对象在创建时,对于两个不同的DB连接要有两个不同的SqlMapClient对象, 假设我们有一个Service类为MyService.java,该类中有两个SqlMapClient对象sqlMapA、sqlMapB分别对应着DB-A、DB-B。 先看看我们的SqlMapClient.java类:(自定义SqlMapClient类,用来演示。) import java.util.Map; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; @SuppressWarnings("unchecked") public class SqlMapClient { public SqlMapClient(String s, String t) { sqlMap = s; type = t; } public SqlMapClient() { } private String type = null; private String sqlMap = null; // get、set方法 略 // 用于演示查询后返回一个String的返回结果 public String selectForObject(String sql, Map in) { return this.toString(); } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)。append("sqlMap", sqlMap) .append("type", type)。toString(); } } MyService.java类实现: import java.util.Map; @SuppressWarnings("unchecked") public class MyService { @DataSource(type="B", sqlMap="com/annotation/sql-map-config-B.xml") private SqlMapClient sqlMapB = null; @DataSource(type="A", sqlMap="com/annotation/sql-map-config-A.xml") private SqlMapClient sqlMapA = null; // get、set方法 略 // 模拟在DB-B数据库取得数据 public String selectForObjectFromB(String sql, Map in) { return sqlMapB.selectForObject("", null); } // 模拟在DB-A数据库取得数据 public String selectForObjectFromA(String sql, Map in) { return sqlMapA.selectForObject("", null); } } 接下来就是我们的注解类:DataSource.java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { /** * Dao的类型 * @return */ String type() default "A"; // 连接的数据库类型 A or B String sqlMap() default ""; // Sql-Map-Config文件的路径,用于加载iBatis的SqlMapClient对象 } 定义资源注入的接口 IFieldWiring.java。 之所以这里要定义这个接口,是为了以后扩展用,我们很方便的定义更多的自定义注解。 IFieldWiring.java import java.lang.annotation.Annotation; import java.lang.reflect.Field; public interface IFieldWiring { Class clazz = obj.getClass(); try { String methodname = "get" + StringUtils.capitalize(fieldName); Method method = clazz.getDeclaredMethod(methodname); method.setAccessible(true); return method.invoke(obj); } catch (Exception e) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (Exception e1) { e1.printStackTrace(); } } return null; } public static void setFieldValue(Object target, String fname, Class fieldClass, Object fieldObj) { if (!fieldClass.isAssignableFrom(fieldObj.getClass())) { return; } Class clazz = target.getClass(); try { Method method = clazz.getDeclaredMethod("set" + Character.toUpperCase(fname.charAt(0)) + fname.substring(1), fieldClass); method.setAccessible(true); method.invoke(target, fieldObj); } catch (Exception e) { try { Field field = clazz.getDeclaredField(fname); field.setAccessible(true); field.set(target, fieldObj); } catch (Exception e1) { e1.printStackTrace(); } } } } 已经基本大功告成了,只要将我们的DataSourceWiring.java类使用起来即可。 MyAnnotationBeanProcessor.java,这个类主要用于为bean对象注入资源。 import java.lang.reflect.Field; public class MyAnnotationBeanProcessor { /** * 注入资源 * @param serviceObject * @param fieldAutoWirings // 所有实现IFieldWiring的接口的对象,我们可以在此扩展 * @throws Exception */ public void wire(Object serviceObject, IFieldWiring fieldAutoWirings) throws Exception { Class cls = serviceObject.getClass(); for (Field field : cls.getDeclaredFields()) { for (IFieldWiring fieldAutoWiring : fieldAutoWirings) { if (field.isAnnotationPresent(fieldAutoWiring.annotationClass())) { fieldAutoWiring.wiring(serviceObject, field); break; } } } } } 好了,开始我们的测试类:FieldWiringTest.java public class FieldWiringTest { public static void main(String args[]) throws Exception { MyAnnotationBeanProcessor processor = new MyAnnotationBeanProcessor(); MyService b = new MyService(); processor.wire(b, new DataSourceWiring()); // 注入DataSource资源 System.out.println(b.selectForObjectFromB("", null)); System.out.println(b.selectForObjectFromA("", null)); } } 执行结果: SqlMapClient[sqlMap=com/annotation/sql-map-config-B.xml,type=B] SqlMapClient[sqlMap=com/annotation/sql-map-config-A.xml,type=A] 由执行结果可以说明DataSource资源已经被我们正确的注入了。 如果想扩展的话,只需要新建一个类实现IFieldWiring接口即可。假设叫InParamWiring.java,实现了接口定义的两个方法后,在使用的时候,只要用以下代码便可将资源注入了: MyAnnotationBeanProcessor processor = new MyAnnotationBeanProcessor(); MyService b = new MyService(); processor.wire(b, new DataSourceWiring(), new InParamWiring()); // 注入DataSource、InParam资源. 更多Java学习技巧,尽在博洋教育。若您想了解java程序培训价格,欢迎向我们的在线老师进行详细了解。

java内部注解是如何实现的

用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。比如,下面这段代码:

@Override

public String toString() {

return "This is String Representation of current object.";

}

上面的代码中,我重写了toString()方法并使用了@Override注解。但是,即使我不使用@Override注解标记代码,程序也能够正常执行。那么,该注解表示什么?这么写有什么好处吗?事实上,@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。如果我不小心拼写错误,例如将toString()写成了toStrring(){double r},而且我也没有使用@Override注解,那程序依然能编译运行。但运行结果会和我期望的大不相同。现在我们了解了什么是注解,并且使用注解有助于阅读程序。

Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符。它是一种由JSR-175标准选择用来描述元数据的一种工具。

为什么要引入注解?

使用Annotation之前(甚至在使用之后),XML被广泛的应用于描述元数据。不知何时开始一些应用开发人员和架构师发现XML的维护越来越糟糕了。他们希望使用一些和代码紧耦合的东西,而不是像XML那样和代码是松耦合的(在某些情况下甚至是完全分离的)代码描述。如果你在Google中搜索“XML vs. annotations”,会看到许多关于这个问题的辩论。最有趣的是XML配置其实就是为了分离代码和配置而引入的。上述两种观点可能会让你很疑惑,两者观点似乎构成了一种循环,但各有利弊。下面我们通过一个例子来理解这两者的区别。

假如你想为应用设置很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来,开发人员也必须认识到这点。

另一个很重要的因素是Annotation定义了一种标准的描述元数据的方式。在这之前,开发人员通常使用他们自己的方式定义元数据。例如,使用标记interfaces,注释,transient关键字等等。每个程序员按照自己的方式定义元数据,而不像Annotation这种标准的方式。

目前,许多框架将XML和Annotation两种方式结合使用,平衡两者之间的利弊。

Annotation是如何工作的?怎么编写自定义的Annotation?

在讲述这部分之前,建议你首先下载Annotation的示例代码AnnotationsSample.zip 。下载之后放在你习惯使用的IDE中,这些代码会帮助你更好的理解Annotation机制。

编写Annotation非常简单,可以将Annotation的定义同接口的定义进行比较。我们来看两个例子:一个是标准的注解@Override,另一个是用户自定义注解@Todo。

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface Override {

}

对于@Override注释你可能有些疑问,它什么都没做,那它是如何检查在父类中有一个同名的函数呢。当然,不要惊讶,我是逗你玩的。@Override注解的定义不仅仅只有这么一点代码。这部分内容很重要,我不得不再次重复:Annotations仅仅是元数据,和业务逻辑无关。理解起来有点困难,但就是这样。如果Annotations不包含业务逻辑,那么必须有人来实现这些逻辑。元数据的用户来做这个事情。Annotations仅仅提供它定义的属性(类/方法/包/域)的信息。Annotations的用户(同样是一些代码)来读取这些信息并实现必要的逻辑。

当我们使用Java的标注Annotations(例如@Override)时,JVM就是一个用户,它在字节码层面工作。到这里,应用开发人员还不能控制也不能使用自定义的注解。因此,我们讲解一下如何编写自定义的Annotations。

我们来逐个讲述编写自定义Annotations的要点。上面的例子中,你看到一些注解应用在注解上。

J2SE5.0版本在 java.lang.annotation提供了四种元注解,专门注解其他的注解:

@Documented –注解是否将包含在JavaDoc中

@Retention –什么时候使用该注解

@Target? –注解用于什么地方

@Inherited – 是否允许子类继承该注解

@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。

@Retention– 定义该注解的生命周期。

RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。

RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。

RetentionPolicy.RUNTIME– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

@Target – 表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。以下是一些可用的参数。需要说明的是:属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性,那么你需要在定义target包含所有的属性。

ElementType.TYPE:用于描述类、接口或enum声明

ElementType.FIELD:用于描述实例变量

ElementType.METHOD

ElementType.PARAMETER

ElementType.CONSTRUCTOR

ElementType.LOCAL_VARIABLE

ElementType.ANNOTATION_TYPE 另一个注释

ElementType.PACKAGE 用于记录java文件的package信息

@Inherited – 定义该注释和子类的关系

那么,注解的内部到底是如何定义的呢?Annotations只支持基本类型、String及枚举类型。注释中所有的属性被定义成方法,并允许提供默认值。

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@interface Todo {

public enum Priority {LOW, MEDIUM, HIGH}

public enum Status {STARTED, NOT_STARTED}

String author() default "Yash";

Priority priority() default Priority.LOW;

Status status() default Status.NOT_STARTED;

}

下面的例子演示了如何使用上面的注解。

@Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)

public void incompleteMethod1() {

//Some business logic is written

//But it’s not complete yet

}

如果注解中只有一个属性,可以直接命名为“value”,使用时无需再标明属性名。

@interface Author{

String value();

}

@Author("Yashwant")

public void someMethod() {

}

但目前为止一切看起来都还不错。我们定义了自己的注解并将其应用在业务逻辑的方法上。现在我们需要写一个用户程序调用我们的注解。这里我们需要使用反射机制。如果你熟悉反射代码,就会知道反射可以提供类名、方法和实例变量对象。所有这些对象都有getAnnotation()这个方法用来返回注解信息。我们需要把这个对象转换为我们自定义的注释(使用 instanceOf()检查之后),同时也可以调用自定义注释里面的方法。看看以下的实例代码,使用了上面的注解:

Class businessLogicClass = BusinessLogic.class;

for(Method method : businessLogicClass.getMethods()) {

Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);

if(todoAnnotation != null) {

System.out.println(" Method Name : " + method.getName());

System.out.println(" Author : " + todoAnnotation.author());

System.out.println(" Priority : " + todoAnnotation.priority());

System.out.println(" Status : " + todoAnnotation.status());

}


网页标题:java注解实现代码注入 java注解编程
本文URL:http://myzitong.com/article/hepeeo.html