如何在java代码中替换Spring的annotation?

       在代码中使用Spring的Annotation会给工作带来很大的便利,但这样也造成了一个问题,就是代码会被Spring的代码污染,代码会跟Spring容器绑死,代码将来不能切换使用其它容器。那能不能不用Spring自身的Annotation同时又不影响代码功能呢?方法是有的,下面就来简单的说一说:

一、对于bean注册,一般Spring中使用如下Annotation
org.springframework.stereotype.Component @Component
org.springframework.stereotype.Repository @Repository
org.springframework.stereotype.Service @Service
org.springframework.stereotype.Controller @Controller
处理这些Annotation的类为:
org.springframework.context.annotation.ClassPathBeanDefinitionScanner
可以用如下两种来替换:
// Java EE 6:
javax.annotation.ManagedBean 

// JSR-330:
javax.inject.Named
二、对于bean的注入和生命周期管理,Spring提供了对非Spring的Annotation的支持:
// JSR-250:
javax.annotation.PostConstruct
javax.annotation.PreDestroy
javax.annotation.Resource

// JAX-WS:
javax.xml.ws.WebServiceRef

// EJB 3:
javax.ejb.EJB
处理这些Annotation的类为:
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
配置方式有如下4种:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
 <property name="alwaysUseJndiLookup" value="true"/>
</bean>

<context:annotation-config />

<context:component-scan /> 
三、对于Bean的注入Spring也提供了对Spring自己的Annotation的支持:
org.springframework.beans.factory.annotation.Autowired  @Autowired
org.springframework.beans.factory.annotation.Value  @Value
处理这些Annotation的类为:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
配置方式:
<context:annotation-config />

<context:component-scan />
可以用如下两种来替换:
// JSR-330:
javax.inject.Inject @Inject
// 这个Annotation会由AutowiredAnnotationBeanPostProcessor处理
// JSR-250:
javax.annotation.Resource @Resource
// 而这个Annotation会由CommonAnnotationBeanPostProcessor处理

其中对于使用@Resource来替换@Value,需要将属性注册成singleton bean,比如在使用Spring-boot的情况下可以实现一个ApplicationContextInitializer

@SpringBootApplication(scanBasePackages = {"com.test"})
public class Application {
    private static final Logger LOG = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.addInitializers(new DefaultApplicationContextInitializer());
        ConfigurableApplicationContext ctx = application.run(args);
        ctx.registerShutdownHook();
    }

    public static class DefaultApplicationContextInitializer implements
            ApplicationContextInitializer<ConfigurableApplicationContext> {

        public void initialize(ConfigurableApplicationContext applicationContext) {
            EnumerablePropertySource<?> ps =
                    (EnumerablePropertySource) applicationContext.getEnvironment().getPropertySources().get(
                            ConfigFileApplicationListener.APPLICATION_CONFIGURATION_PROPERTY_SOURCE_NAME);

            Map<String, Object> propMap = new HashMap<>();
            for (String propertyName : ps.getPropertyNames()) {
                propMap.put(propertyName, ps.getProperty(propertyName));
            }

            String info = "registerPropertyBean:";

            for (String propertyName : propMap.keySet()) {
                info += System.lineSeparator() + "propertyName=" + propertyName + ", propertyValue=" +
                        propMap.get(propertyName);
                applicationContext.getBeanFactory().registerSingleton(propertyName, propMap.get(propertyName));
            }

            LOG.info(info);
        }
    }
}

@Value("${project.name}")
private String projectName;
// 可替换为
@Resource(name="project.name")
private String projectName;
四、对bean注册事务或对bean中的方法注册事务,一般Spring中使用如下Annotation
org.springframework.transaction.annotation.Transactional  @Transactional
处理这些Annotation的类为:
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
可以用如下两种来替换:
// JTA 1.2
javax.transaction.Transactional
// EJB3
javax.ejb.TransactionAttribute
      经过以上几种修改后,业务代码将完全去Spring化,当需要切换使用其它容器时,只要把引导代码(比如:Application类)做一下修改或提供另一个实现就可以了。






猜你喜欢

转载自blog.csdn.net/netyeaxi/article/details/79278485