我的Service和dao既没在applicationContext.xml中注册也没加注解哦,亲!
下面到重点了,写个测试类,看看到底该这样在程序运行时动态的把bean注册进spring容器,然后就跟事先在applicationContext.xml中注册过该bean一样,以前怎么从spring容器中拿bean实例,现在就怎么拿,对于用户来说,bean是静态注册的还是动态注册的,毫无知觉的。
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.spel.ast.Identifier;
import org.springframework.util.ClassUtils;
import com.nicolas.service.TestService;
import com.nicolas.service.impl.TestServiceImpl;
import com.sun.org.apache.bcel.internal.util.ClassPath;
public class Test2 {
public static void main(String[] args) throws BeanDefinitionStoreException, ClassNotFoundException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml");
//ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
//TestService testService = new TestServiceImpl();
//这里是动态注册单例,不过实例要事先自己new,这种做法不推荐
//beanFactory.registerSingleton("testService", testService);
//这里是动态注册非单例bean,把setScope("prototype") 改为setScope("singleton")就是单例注册了,推荐使用这种方式动态注册
//有的同学可能会问,采用动态注册Bean有上面好处,好处就是:
//你的bean再也不需要在Spring的applicationContext.xml中注册了,也不需要在你的bean上加什么@Component、@Resource、@Service等各种bean相关的注解了
//从bean注册中彻底解放了,你甚至可以自己写一个监听器(比如实现一个ServletContextListener),在项目启动时,搜索项目中需要注册的bean通过现在这种方法动态注册,后来新增的bean可以额外再动态注册,是不是感觉世界又美好了很多
beanFactory.registerBeanDefinition("testDao", BeanDefinitionBuilder.genericBeanDefinition(Class.forName("com.nicolas.dao.impl.TestDaoImpl")).setScope("prototype").getRawBeanDefinition());
beanFactory.registerBeanDefinition("testService", BeanDefinitionBuilder.genericBeanDefinition(Class.forName("com.nicolas.service.impl.TestServiceImpl"))
.setScope("prototype").addPropertyReference("testDao", "testDao").getRawBeanDefinition());
TestService testService2 = (TestService)beanFactory.getBean("testService");
TestService testService3 = (TestService)beanFactory.getBean("testService");
//判断是否为单例,false就表明不是单例
//com.nicolas.service.impl.TestServiceImpl这里的包路径你其实可以通过项目某个包下的所有以某某字符串结尾的类就可以获取得到
//比如你搜索项目中com.yida.service.impl包下的所有以Impl结尾的类,你得到了类,那通过类就可以知道类的名称,再拼接上包路径,那么
//那上面写死的包路径你就可以动态获取了,这里仅仅只是为了测试
System.out.println(testService2.equals(testService3));
testService2.sayHello();
}
上面的代码中注释已经说的很清楚了,就不再细说了。我这么折腾到底能带来什么好处?我想你肯定在心底会这么问,这么折腾还不是为了偷懒,不想写配置文件,不想记各种注解,蛋疼有木有?写多了自然就会有:能不能自动配置或者自动注册诸如之类的想法,不会偷懒的程序员算不上好程序员。OK,解释完毕!我今晚也折腾完毕!感谢大家一如既往对我博客的关注,我自我感觉文笔不怎么样,很少出来献丑。偶尔是有点忍不住,就瞎写写,大家勉强凑合凑合看吧,觉得对你有帮助我就很欣慰了,觉得写的不好请正面指正,谢谢!闲话不扯了,
Sorry,上面提到说搜索某个包下的所有类,但是没贴出来关键代码,以免大家说我光说不练忽悠人,还是决定把该实现代码贴出来,其实也不是我写的,是网上google来的,我觉得有价值,自己也测试通过了,就分享给大家了!
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
public class ClassPathScanHandler {
private static final Logger logger = Logger
.getLogger(ClassPathScanHandler.class);
private boolean excludeInner = true;
private boolean checkInOrEx = true;
private List classFilters = null;
public ClassPathScanHandler() {
}
public ClassPathScanHandler(Boolean excludeInner, Boolean checkInOrEx,
List classFilters) {
this.excludeInner = excludeInner;
this.checkInOrEx = checkInOrEx;
this.classFilters = classFilters;
}
public Set> getPackageAllClasses(String basePackage,
boolean recursive) {
Set> classes = new LinkedHashSet>();
String packageName = basePackage;
if (packageName.endsWith(".")) {
packageName = packageName
.substring(0, packageName.lastIndexOf('.'));
}
String package2Path = packageName.replace('.', '/');
Enumeration dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(
package2Path);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
logger.info("扫描file类型的class文件....");
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
doScanPackageClassesByFile(classes, packageName, filePath,
recursive);
} else if ("jar".equals(protocol)) {
logger.info("扫描jar文件中的类....");
doScanPackageClassesByJar(packageName, url, recursive,
classes);
}
}
} catch (IOException e) {
logger.error("IOException error:", e);
}
return classes;
}
private void doScanPackageClassesByJar(String basePackage, URL url,
final boolean recursive, Set> classes) {
String packageName = basePackage;
String package2Path = packageName.replace('.', '/');
JarFile jar;
try {
jar = ((JarURLConnection) url.openConnection()).getJarFile();
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (!name.startsWith(package2Path) || entry.isDirectory()) {
continue;
}
// 判断是否递归搜索子包
if (!recursive
&& name.lastIndexOf('/') != package2Path.length()) {
continue;
}
// 判断是否过滤 inner class
if (this.excludeInner && name.indexOf('$') != -1) {
logger.info("exclude inner class with name:" + name);
continue;
}
String classSimpleName = name
.substring(name.lastIndexOf('/') + 1);
// 判定是否符合过滤条件
if (this.filterClassName(classSimpleName)) {
String className = name.replace('/', '.');
className = className.substring(0, className.length() - 6);
try {
classes.add(Thread.currentThread()
.getContextClassLoader().loadClass(className));
} catch (ClassNotFoundException e) {
logger.error("Class.forName error:", e);
}
}
}
} catch (IOException e) {
logger.error("IOException error:", e);
}
}
private void doScanPackageClassesByFile(Set> classes,
String packageName, String packagePath, boolean recursive) {
File dir = new File(packagePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
final boolean fileRecursive = recursive;
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义文件过滤规则
public boolean accept(File file) {
if (file.isDirectory()) {
return fileRecursive;
}
String filename = file.getName();
if (excludeInner && filename.indexOf('$') != -1) {
logger.info("exclude inner class with name:" + filename);
return false;
}
return filterClassName(filename);
}
});
for (File file : dirfiles) {
if (file.isDirectory()) {
doScanPackageClassesByFile(classes, packageName + "."
+ file.getName(), file.getAbsolutePath(), recursive);
} else {
String className = file.getName().substring(0,
file.getName().length() - 6);
try {
classes.add(Thread.currentThread().getContextClassLoader()
.loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
logger.error("IOException error:", e);
}
}
}
}
private boolean filterClassName(String className) {
if (!className.endsWith(".class")) {
return false;
}
if (null == this.classFilters || this.classFilters.isEmpty()) {
return true;
}
String tmpName = className.substring(0, className.length() - 6);
boolean flag = false;
for (String str : classFilters) {
String tmpreg = "^" + str.replace("*", ".*") + "$";
Pattern p = Pattern.compile(tmpreg);
if (p.matcher(tmpName).find()) {
flag = true;
break;
}
}
return (checkInOrEx && flag) || (!checkInOrEx && !flag);
}
public boolean isExcludeInner() {
return excludeInner;
}
public boolean isCheckInOrEx() {
return checkInOrEx;
}
public List getClassFilters() {
return classFilters;
}
public void setExcludeInner(boolean pExcludeInner) {
excludeInner = pExcludeInner;
}
public void setCheckInOrEx(boolean pCheckInOrEx) {
checkInOrEx = pCheckInOrEx;
}
public void setClassFilters(ListpClassFilters) {
classFilters = pClassFilters;
}
public static void main(String[] args) {
ClassPathScanHandler handler = new ClassPathScanHandler();
Set> classSet = handler.getPackageAllClasses(
"com.nicolas.service.impl", true);
for (Iterator iterator = classSet.iterator(); iterator.hasNext();) {
Class clazz = (Class) iterator.next();
System.out.println(clazz.getName());
}
}
}